| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  *  linux/fs/ufs/ialloc.c | 
 | 3 |  * | 
 | 4 |  * Copyright (c) 1998 | 
 | 5 |  * Daniel Pirkl <daniel.pirkl@email.cz> | 
 | 6 |  * Charles University, Faculty of Mathematics and Physics | 
 | 7 |  * | 
 | 8 |  *  from | 
 | 9 |  * | 
 | 10 |  *  linux/fs/ext2/ialloc.c | 
 | 11 |  * | 
 | 12 |  * Copyright (C) 1992, 1993, 1994, 1995 | 
 | 13 |  * Remy Card (card@masi.ibp.fr) | 
 | 14 |  * Laboratoire MASI - Institut Blaise Pascal | 
 | 15 |  * Universite Pierre et Marie Curie (Paris VI) | 
 | 16 |  * | 
 | 17 |  *  BSD ufs-inspired inode and directory allocation by  | 
 | 18 |  *  Stephen Tweedie (sct@dcs.ed.ac.uk), 1993 | 
 | 19 |  *  Big-endian to little-endian byte-swapping/bitmaps by | 
 | 20 |  *        David S. Miller (davem@caip.rutgers.edu), 1995 | 
| Evgeniy Dushistov | 3313e29 | 2007-02-12 00:54:31 -0800 | [diff] [blame] | 21 |  * | 
 | 22 |  * UFS2 write support added by | 
 | 23 |  * Evgeniy Dushistov <dushistov@mail.ru>, 2007 | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 24 |  */ | 
 | 25 |  | 
 | 26 | #include <linux/fs.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 27 | #include <linux/time.h> | 
 | 28 | #include <linux/stat.h> | 
 | 29 | #include <linux/string.h> | 
 | 30 | #include <linux/quotaops.h> | 
 | 31 | #include <linux/buffer_head.h> | 
 | 32 | #include <linux/sched.h> | 
 | 33 | #include <linux/bitops.h> | 
 | 34 | #include <asm/byteorder.h> | 
 | 35 |  | 
| Mike Frysinger | e542059 | 2008-02-08 04:21:31 -0800 | [diff] [blame] | 36 | #include "ufs_fs.h" | 
| Christoph Hellwig | bcd6d4e | 2007-10-16 23:26:51 -0700 | [diff] [blame] | 37 | #include "ufs.h" | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 38 | #include "swab.h" | 
 | 39 | #include "util.h" | 
 | 40 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 41 | /* | 
 | 42 |  * NOTE! When we get the inode, we're the only people | 
 | 43 |  * that have access to it, and as such there are no | 
 | 44 |  * race conditions we have to worry about. The inode | 
 | 45 |  * is not on the hash-lists, and it cannot be reached | 
 | 46 |  * through the filesystem because the directory entry | 
 | 47 |  * has been deleted earlier. | 
 | 48 |  * | 
 | 49 |  * HOWEVER: we must make sure that we get no aliases, | 
 | 50 |  * which means that we have to call "clear_inode()" | 
 | 51 |  * _before_ we mark the inode not in use in the inode | 
 | 52 |  * bitmaps. Otherwise a newly created file might use | 
 | 53 |  * the same inode number (not actually the same pointer | 
 | 54 |  * though), and then we'd have two inodes sharing the | 
 | 55 |  * same inode number and space on the harddisk. | 
 | 56 |  */ | 
 | 57 | void ufs_free_inode (struct inode * inode) | 
 | 58 | { | 
 | 59 | 	struct super_block * sb; | 
 | 60 | 	struct ufs_sb_private_info * uspi; | 
 | 61 | 	struct ufs_super_block_first * usb1; | 
 | 62 | 	struct ufs_cg_private_info * ucpi; | 
 | 63 | 	struct ufs_cylinder_group * ucg; | 
 | 64 | 	int is_directory; | 
 | 65 | 	unsigned ino, cg, bit; | 
 | 66 | 	 | 
| Evgeniy Dushistov | abf5d15 | 2006-06-25 05:47:24 -0700 | [diff] [blame] | 67 | 	UFSD("ENTER, ino %lu\n", inode->i_ino); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 68 |  | 
 | 69 | 	sb = inode->i_sb; | 
 | 70 | 	uspi = UFS_SB(sb)->s_uspi; | 
| Evgeniy | 7b4ee73 | 2006-01-14 11:42:06 +0300 | [diff] [blame] | 71 | 	usb1 = ubh_get_usb_first(uspi); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 72 | 	 | 
 | 73 | 	ino = inode->i_ino; | 
 | 74 |  | 
 | 75 | 	lock_super (sb); | 
 | 76 |  | 
 | 77 | 	if (!((ino > 1) && (ino < (uspi->s_ncg * uspi->s_ipg )))) { | 
 | 78 | 		ufs_warning(sb, "ufs_free_inode", "reserved inode or nonexistent inode %u\n", ino); | 
 | 79 | 		unlock_super (sb); | 
 | 80 | 		return; | 
 | 81 | 	} | 
 | 82 | 	 | 
 | 83 | 	cg = ufs_inotocg (ino); | 
 | 84 | 	bit = ufs_inotocgoff (ino); | 
 | 85 | 	ucpi = ufs_load_cylinder (sb, cg); | 
 | 86 | 	if (!ucpi) { | 
 | 87 | 		unlock_super (sb); | 
 | 88 | 		return; | 
 | 89 | 	} | 
| Evgeniy Dushistov | 9695ef1 | 2006-06-25 05:47:22 -0700 | [diff] [blame] | 90 | 	ucg = ubh_get_ucg(UCPI_UBH(ucpi)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 91 | 	if (!ufs_cg_chkmagic(sb, ucg)) | 
 | 92 | 		ufs_panic (sb, "ufs_free_fragments", "internal error, bad cg magic number"); | 
 | 93 |  | 
 | 94 | 	ucg->cg_time = cpu_to_fs32(sb, get_seconds()); | 
 | 95 |  | 
 | 96 | 	is_directory = S_ISDIR(inode->i_mode); | 
 | 97 |  | 
| Christoph Hellwig | 63936dd | 2010-03-03 09:05:01 -0500 | [diff] [blame] | 98 | 	dquot_free_inode(inode); | 
| Christoph Hellwig | 9f75475 | 2010-03-03 09:05:05 -0500 | [diff] [blame] | 99 | 	dquot_drop(inode); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 100 |  | 
 | 101 | 	clear_inode (inode); | 
 | 102 |  | 
| Evgeniy Dushistov | 9695ef1 | 2006-06-25 05:47:22 -0700 | [diff] [blame] | 103 | 	if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit)) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 104 | 		ufs_error(sb, "ufs_free_inode", "bit already cleared for inode %u", ino); | 
 | 105 | 	else { | 
| Evgeniy Dushistov | 9695ef1 | 2006-06-25 05:47:22 -0700 | [diff] [blame] | 106 | 		ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 107 | 		if (ino < ucpi->c_irotor) | 
 | 108 | 			ucpi->c_irotor = ino; | 
 | 109 | 		fs32_add(sb, &ucg->cg_cs.cs_nifree, 1); | 
| Evgeniy Dushistov | ee3ffd6 | 2006-06-25 05:47:30 -0700 | [diff] [blame] | 110 | 		uspi->cs_total.cs_nifree++; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 111 | 		fs32_add(sb, &UFS_SB(sb)->fs_cs(cg).cs_nifree, 1); | 
 | 112 |  | 
 | 113 | 		if (is_directory) { | 
 | 114 | 			fs32_sub(sb, &ucg->cg_cs.cs_ndir, 1); | 
| Evgeniy Dushistov | ee3ffd6 | 2006-06-25 05:47:30 -0700 | [diff] [blame] | 115 | 			uspi->cs_total.cs_ndir--; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 116 | 			fs32_sub(sb, &UFS_SB(sb)->fs_cs(cg).cs_ndir, 1); | 
 | 117 | 		} | 
 | 118 | 	} | 
 | 119 |  | 
| Evgeniy Dushistov | 9695ef1 | 2006-06-25 05:47:22 -0700 | [diff] [blame] | 120 | 	ubh_mark_buffer_dirty (USPI_UBH(uspi)); | 
 | 121 | 	ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 122 | 	if (sb->s_flags & MS_SYNCHRONOUS) { | 
| Evgeniy Dushistov | 098d5af | 2006-06-25 05:47:31 -0700 | [diff] [blame] | 123 | 		ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); | 
| Evgeniy Dushistov | 9695ef1 | 2006-06-25 05:47:22 -0700 | [diff] [blame] | 124 | 		ubh_wait_on_buffer (UCPI_UBH(ucpi)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 125 | 	} | 
 | 126 | 	 | 
 | 127 | 	sb->s_dirt = 1; | 
 | 128 | 	unlock_super (sb); | 
| Evgeniy Dushistov | abf5d15 | 2006-06-25 05:47:24 -0700 | [diff] [blame] | 129 | 	UFSD("EXIT\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 130 | } | 
 | 131 |  | 
 | 132 | /* | 
| Evgeniy Dushistov | 3313e29 | 2007-02-12 00:54:31 -0800 | [diff] [blame] | 133 |  * Nullify new chunk of inodes, | 
 | 134 |  * BSD people also set ui_gen field of inode | 
 | 135 |  * during nullification, but we not care about | 
 | 136 |  * that because of linux ufs do not support NFS | 
 | 137 |  */ | 
 | 138 | static void ufs2_init_inodes_chunk(struct super_block *sb, | 
 | 139 | 				   struct ufs_cg_private_info *ucpi, | 
 | 140 | 				   struct ufs_cylinder_group *ucg) | 
 | 141 | { | 
 | 142 | 	struct buffer_head *bh; | 
 | 143 | 	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | 
 | 144 | 	sector_t beg = uspi->s_sbbase + | 
 | 145 | 		ufs_inotofsba(ucpi->c_cgx * uspi->s_ipg + | 
 | 146 | 			      fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk)); | 
 | 147 | 	sector_t end = beg + uspi->s_fpb; | 
 | 148 |  | 
 | 149 | 	UFSD("ENTER cgno %d\n", ucpi->c_cgx); | 
 | 150 |  | 
 | 151 | 	for (; beg < end; ++beg) { | 
 | 152 | 		bh = sb_getblk(sb, beg); | 
 | 153 | 		lock_buffer(bh); | 
 | 154 | 		memset(bh->b_data, 0, sb->s_blocksize); | 
 | 155 | 		set_buffer_uptodate(bh); | 
 | 156 | 		mark_buffer_dirty(bh); | 
 | 157 | 		unlock_buffer(bh); | 
 | 158 | 		if (sb->s_flags & MS_SYNCHRONOUS) | 
 | 159 | 			sync_dirty_buffer(bh); | 
 | 160 | 		brelse(bh); | 
 | 161 | 	} | 
 | 162 |  | 
 | 163 | 	fs32_add(sb, &ucg->cg_u.cg_u2.cg_initediblk, uspi->s_inopb); | 
 | 164 | 	ubh_mark_buffer_dirty(UCPI_UBH(ucpi)); | 
 | 165 | 	if (sb->s_flags & MS_SYNCHRONOUS) { | 
 | 166 | 		ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); | 
 | 167 | 		ubh_wait_on_buffer(UCPI_UBH(ucpi)); | 
 | 168 | 	} | 
 | 169 |  | 
 | 170 | 	UFSD("EXIT\n"); | 
 | 171 | } | 
 | 172 |  | 
 | 173 | /* | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 174 |  * There are two policies for allocating an inode.  If the new inode is | 
 | 175 |  * a directory, then a forward search is made for a block group with both | 
 | 176 |  * free space and a low directory-to-inode ratio; if that fails, then of | 
 | 177 |  * the groups with above-average free space, that group with the fewest | 
 | 178 |  * directories already is chosen. | 
 | 179 |  * | 
 | 180 |  * For other inodes, search forward from the parent directory's block | 
 | 181 |  * group to find a free inode. | 
 | 182 |  */ | 
 | 183 | struct inode * ufs_new_inode(struct inode * dir, int mode) | 
 | 184 | { | 
 | 185 | 	struct super_block * sb; | 
 | 186 | 	struct ufs_sb_info * sbi; | 
 | 187 | 	struct ufs_sb_private_info * uspi; | 
 | 188 | 	struct ufs_super_block_first * usb1; | 
 | 189 | 	struct ufs_cg_private_info * ucpi; | 
 | 190 | 	struct ufs_cylinder_group * ucg; | 
 | 191 | 	struct inode * inode; | 
 | 192 | 	unsigned cg, bit, i, j, start; | 
 | 193 | 	struct ufs_inode_info *ufsi; | 
| Evgeniy Dushistov | 3313e29 | 2007-02-12 00:54:31 -0800 | [diff] [blame] | 194 | 	int err = -ENOSPC; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 195 |  | 
| Evgeniy Dushistov | abf5d15 | 2006-06-25 05:47:24 -0700 | [diff] [blame] | 196 | 	UFSD("ENTER\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 197 | 	 | 
 | 198 | 	/* Cannot create files in a deleted directory */ | 
 | 199 | 	if (!dir || !dir->i_nlink) | 
 | 200 | 		return ERR_PTR(-EPERM); | 
 | 201 | 	sb = dir->i_sb; | 
 | 202 | 	inode = new_inode(sb); | 
 | 203 | 	if (!inode) | 
 | 204 | 		return ERR_PTR(-ENOMEM); | 
 | 205 | 	ufsi = UFS_I(inode); | 
 | 206 | 	sbi = UFS_SB(sb); | 
 | 207 | 	uspi = sbi->s_uspi; | 
| Evgeniy | 7b4ee73 | 2006-01-14 11:42:06 +0300 | [diff] [blame] | 208 | 	usb1 = ubh_get_usb_first(uspi); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 209 |  | 
 | 210 | 	lock_super (sb); | 
 | 211 |  | 
 | 212 | 	/* | 
 | 213 | 	 * Try to place the inode in its parent directory | 
 | 214 | 	 */ | 
 | 215 | 	i = ufs_inotocg(dir->i_ino); | 
 | 216 | 	if (sbi->fs_cs(i).cs_nifree) { | 
 | 217 | 		cg = i; | 
 | 218 | 		goto cg_found; | 
 | 219 | 	} | 
 | 220 |  | 
 | 221 | 	/* | 
 | 222 | 	 * Use a quadratic hash to find a group with a free inode | 
 | 223 | 	 */ | 
 | 224 | 	for ( j = 1; j < uspi->s_ncg; j <<= 1 ) { | 
 | 225 | 		i += j; | 
 | 226 | 		if (i >= uspi->s_ncg) | 
 | 227 | 			i -= uspi->s_ncg; | 
 | 228 | 		if (sbi->fs_cs(i).cs_nifree) { | 
 | 229 | 			cg = i; | 
 | 230 | 			goto cg_found; | 
 | 231 | 		} | 
 | 232 | 	} | 
 | 233 |  | 
 | 234 | 	/* | 
 | 235 | 	 * That failed: try linear search for a free inode | 
 | 236 | 	 */ | 
 | 237 | 	i = ufs_inotocg(dir->i_ino) + 1; | 
 | 238 | 	for (j = 2; j < uspi->s_ncg; j++) { | 
 | 239 | 		i++; | 
 | 240 | 		if (i >= uspi->s_ncg) | 
 | 241 | 			i = 0; | 
 | 242 | 		if (sbi->fs_cs(i).cs_nifree) { | 
 | 243 | 			cg = i; | 
 | 244 | 			goto cg_found; | 
 | 245 | 		} | 
 | 246 | 	} | 
| Evgeniy Dushistov | 3313e29 | 2007-02-12 00:54:31 -0800 | [diff] [blame] | 247 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 248 | 	goto failed; | 
 | 249 |  | 
 | 250 | cg_found: | 
 | 251 | 	ucpi = ufs_load_cylinder (sb, cg); | 
| Evgeniy Dushistov | 3313e29 | 2007-02-12 00:54:31 -0800 | [diff] [blame] | 252 | 	if (!ucpi) { | 
 | 253 | 		err = -EIO; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 254 | 		goto failed; | 
| Evgeniy Dushistov | 3313e29 | 2007-02-12 00:54:31 -0800 | [diff] [blame] | 255 | 	} | 
| Evgeniy Dushistov | 9695ef1 | 2006-06-25 05:47:22 -0700 | [diff] [blame] | 256 | 	ucg = ubh_get_ucg(UCPI_UBH(ucpi)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 257 | 	if (!ufs_cg_chkmagic(sb, ucg))  | 
 | 258 | 		ufs_panic (sb, "ufs_new_inode", "internal error, bad cg magic number"); | 
 | 259 |  | 
 | 260 | 	start = ucpi->c_irotor; | 
| Evgeniy Dushistov | 9695ef1 | 2006-06-25 05:47:22 -0700 | [diff] [blame] | 261 | 	bit = ubh_find_next_zero_bit (UCPI_UBH(ucpi), ucpi->c_iusedoff, uspi->s_ipg, start); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 262 | 	if (!(bit < uspi->s_ipg)) { | 
| Evgeniy Dushistov | 9695ef1 | 2006-06-25 05:47:22 -0700 | [diff] [blame] | 263 | 		bit = ubh_find_first_zero_bit (UCPI_UBH(ucpi), ucpi->c_iusedoff, start); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 264 | 		if (!(bit < start)) { | 
 | 265 | 			ufs_error (sb, "ufs_new_inode", | 
 | 266 | 			    "cylinder group %u corrupted - error in inode bitmap\n", cg); | 
| Evgeniy Dushistov | 3313e29 | 2007-02-12 00:54:31 -0800 | [diff] [blame] | 267 | 			err = -EIO; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 268 | 			goto failed; | 
 | 269 | 		} | 
 | 270 | 	} | 
| Evgeniy Dushistov | abf5d15 | 2006-06-25 05:47:24 -0700 | [diff] [blame] | 271 | 	UFSD("start = %u, bit = %u, ipg = %u\n", start, bit, uspi->s_ipg); | 
| Evgeniy Dushistov | 9695ef1 | 2006-06-25 05:47:22 -0700 | [diff] [blame] | 272 | 	if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit)) | 
 | 273 | 		ubh_setbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 274 | 	else { | 
 | 275 | 		ufs_panic (sb, "ufs_new_inode", "internal error"); | 
| Evgeniy Dushistov | 3313e29 | 2007-02-12 00:54:31 -0800 | [diff] [blame] | 276 | 		err = -EIO; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 277 | 		goto failed; | 
 | 278 | 	} | 
| Evgeniy Dushistov | 3313e29 | 2007-02-12 00:54:31 -0800 | [diff] [blame] | 279 |  | 
 | 280 | 	if (uspi->fs_magic == UFS2_MAGIC) { | 
 | 281 | 		u32 initediblk = fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk); | 
 | 282 |  | 
 | 283 | 		if (bit + uspi->s_inopb > initediblk && | 
 | 284 | 		    initediblk < fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_niblk)) | 
 | 285 | 			ufs2_init_inodes_chunk(sb, ucpi, ucg); | 
 | 286 | 	} | 
 | 287 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 288 | 	fs32_sub(sb, &ucg->cg_cs.cs_nifree, 1); | 
| Evgeniy Dushistov | ee3ffd6 | 2006-06-25 05:47:30 -0700 | [diff] [blame] | 289 | 	uspi->cs_total.cs_nifree--; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 290 | 	fs32_sub(sb, &sbi->fs_cs(cg).cs_nifree, 1); | 
 | 291 | 	 | 
 | 292 | 	if (S_ISDIR(mode)) { | 
 | 293 | 		fs32_add(sb, &ucg->cg_cs.cs_ndir, 1); | 
| Evgeniy Dushistov | ee3ffd6 | 2006-06-25 05:47:30 -0700 | [diff] [blame] | 294 | 		uspi->cs_total.cs_ndir++; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 295 | 		fs32_add(sb, &sbi->fs_cs(cg).cs_ndir, 1); | 
 | 296 | 	} | 
| Evgeniy Dushistov | 9695ef1 | 2006-06-25 05:47:22 -0700 | [diff] [blame] | 297 | 	ubh_mark_buffer_dirty (USPI_UBH(uspi)); | 
 | 298 | 	ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 299 | 	if (sb->s_flags & MS_SYNCHRONOUS) { | 
| Evgeniy Dushistov | 098d5af | 2006-06-25 05:47:31 -0700 | [diff] [blame] | 300 | 		ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); | 
| Evgeniy Dushistov | 9695ef1 | 2006-06-25 05:47:22 -0700 | [diff] [blame] | 301 | 		ubh_wait_on_buffer (UCPI_UBH(ucpi)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 302 | 	} | 
 | 303 | 	sb->s_dirt = 1; | 
 | 304 |  | 
| Evgeniy Dushistov | 3313e29 | 2007-02-12 00:54:31 -0800 | [diff] [blame] | 305 | 	inode->i_ino = cg * uspi->s_ipg + bit; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 306 | 	inode->i_mode = mode; | 
| David Howells | a5f773a | 2008-11-14 10:39:04 +1100 | [diff] [blame] | 307 | 	inode->i_uid = current_fsuid(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 308 | 	if (dir->i_mode & S_ISGID) { | 
 | 309 | 		inode->i_gid = dir->i_gid; | 
 | 310 | 		if (S_ISDIR(mode)) | 
 | 311 | 			inode->i_mode |= S_ISGID; | 
 | 312 | 	} else | 
| David Howells | a5f773a | 2008-11-14 10:39:04 +1100 | [diff] [blame] | 313 | 		inode->i_gid = current_fsgid(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 314 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 315 | 	inode->i_blocks = 0; | 
| Evgeniy Dushistov | 3313e29 | 2007-02-12 00:54:31 -0800 | [diff] [blame] | 316 | 	inode->i_generation = 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 317 | 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; | 
 | 318 | 	ufsi->i_flags = UFS_I(dir)->i_flags; | 
 | 319 | 	ufsi->i_lastfrag = 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 320 | 	ufsi->i_shadow = 0; | 
 | 321 | 	ufsi->i_osync = 0; | 
 | 322 | 	ufsi->i_oeftflag = 0; | 
| Evgeniy Dushistov | dd187a2 | 2006-06-25 05:47:25 -0700 | [diff] [blame] | 323 | 	ufsi->i_dir_start_lookup = 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 324 | 	memset(&ufsi->i_u1, 0, sizeof(ufsi->i_u1)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 325 | 	insert_inode_hash(inode); | 
 | 326 | 	mark_inode_dirty(inode); | 
 | 327 |  | 
| Evgeniy Dushistov | 3313e29 | 2007-02-12 00:54:31 -0800 | [diff] [blame] | 328 | 	if (uspi->fs_magic == UFS2_MAGIC) { | 
 | 329 | 		struct buffer_head *bh; | 
 | 330 | 		struct ufs2_inode *ufs2_inode; | 
 | 331 |  | 
 | 332 | 		/* | 
 | 333 | 		 * setup birth date, we do it here because of there is no sense | 
 | 334 | 		 * to hold it in struct ufs_inode_info, and lose 64 bit | 
 | 335 | 		 */ | 
 | 336 | 		bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino)); | 
 | 337 | 		if (!bh) { | 
 | 338 | 			ufs_warning(sb, "ufs_read_inode", | 
 | 339 | 				    "unable to read inode %lu\n", | 
 | 340 | 				    inode->i_ino); | 
 | 341 | 			err = -EIO; | 
 | 342 | 			goto fail_remove_inode; | 
 | 343 | 		} | 
 | 344 | 		lock_buffer(bh); | 
 | 345 | 		ufs2_inode = (struct ufs2_inode *)bh->b_data; | 
 | 346 | 		ufs2_inode += ufs_inotofsbo(inode->i_ino); | 
| Evgeniy Dushistov | 2189850 | 2007-03-16 13:38:07 -0800 | [diff] [blame] | 347 | 		ufs2_inode->ui_birthtime = cpu_to_fs64(sb, CURRENT_TIME.tv_sec); | 
 | 348 | 		ufs2_inode->ui_birthnsec = cpu_to_fs32(sb, CURRENT_TIME.tv_nsec); | 
| Evgeniy Dushistov | 3313e29 | 2007-02-12 00:54:31 -0800 | [diff] [blame] | 349 | 		mark_buffer_dirty(bh); | 
 | 350 | 		unlock_buffer(bh); | 
 | 351 | 		if (sb->s_flags & MS_SYNCHRONOUS) | 
 | 352 | 			sync_dirty_buffer(bh); | 
 | 353 | 		brelse(bh); | 
 | 354 | 	} | 
 | 355 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 356 | 	unlock_super (sb); | 
 | 357 |  | 
| Christoph Hellwig | 871a293 | 2010-03-03 09:05:07 -0500 | [diff] [blame] | 358 | 	dquot_initialize(inode); | 
| Christoph Hellwig | 63936dd | 2010-03-03 09:05:01 -0500 | [diff] [blame] | 359 | 	err = dquot_alloc_inode(inode); | 
 | 360 | 	if (err) { | 
| Christoph Hellwig | 9f75475 | 2010-03-03 09:05:05 -0500 | [diff] [blame] | 361 | 		dquot_drop(inode); | 
| Evgeniy Dushistov | 3313e29 | 2007-02-12 00:54:31 -0800 | [diff] [blame] | 362 | 		goto fail_without_unlock; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 363 | 	} | 
 | 364 |  | 
| Evgeniy Dushistov | abf5d15 | 2006-06-25 05:47:24 -0700 | [diff] [blame] | 365 | 	UFSD("allocating inode %lu\n", inode->i_ino); | 
 | 366 | 	UFSD("EXIT\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 367 | 	return inode; | 
 | 368 |  | 
| Evgeniy Dushistov | 3313e29 | 2007-02-12 00:54:31 -0800 | [diff] [blame] | 369 | fail_remove_inode: | 
 | 370 | 	unlock_super(sb); | 
 | 371 | fail_without_unlock: | 
 | 372 | 	inode->i_flags |= S_NOQUOTA; | 
 | 373 | 	inode->i_nlink = 0; | 
 | 374 | 	iput(inode); | 
 | 375 | 	UFSD("EXIT (FAILED): err %d\n", err); | 
 | 376 | 	return ERR_PTR(err); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 377 | failed: | 
 | 378 | 	unlock_super (sb); | 
 | 379 | 	make_bad_inode(inode); | 
 | 380 | 	iput (inode); | 
| Evgeniy Dushistov | 3313e29 | 2007-02-12 00:54:31 -0800 | [diff] [blame] | 381 | 	UFSD("EXIT (FAILED): err %d\n", err); | 
 | 382 | 	return ERR_PTR(err); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 383 | } |