diff options
Diffstat (limited to 'fs/ufs/ialloc.c')
-rw-r--r-- | fs/ufs/ialloc.c | 116 |
1 files changed, 103 insertions, 13 deletions
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c index 2ad1259c6eca..b868878009b6 100644 --- a/fs/ufs/ialloc.c +++ b/fs/ufs/ialloc.c | |||
@@ -18,6 +18,9 @@ | |||
18 | * Stephen Tweedie (sct@dcs.ed.ac.uk), 1993 | 18 | * Stephen Tweedie (sct@dcs.ed.ac.uk), 1993 |
19 | * Big-endian to little-endian byte-swapping/bitmaps by | 19 | * Big-endian to little-endian byte-swapping/bitmaps by |
20 | * David S. Miller (davem@caip.rutgers.edu), 1995 | 20 | * David S. Miller (davem@caip.rutgers.edu), 1995 |
21 | * | ||
22 | * UFS2 write support added by | ||
23 | * Evgeniy Dushistov <dushistov@mail.ru>, 2007 | ||
21 | */ | 24 | */ |
22 | 25 | ||
23 | #include <linux/fs.h> | 26 | #include <linux/fs.h> |
@@ -126,6 +129,47 @@ void ufs_free_inode (struct inode * inode) | |||
126 | } | 129 | } |
127 | 130 | ||
128 | /* | 131 | /* |
132 | * Nullify new chunk of inodes, | ||
133 | * BSD people also set ui_gen field of inode | ||
134 | * during nullification, but we not care about | ||
135 | * that because of linux ufs do not support NFS | ||
136 | */ | ||
137 | static void ufs2_init_inodes_chunk(struct super_block *sb, | ||
138 | struct ufs_cg_private_info *ucpi, | ||
139 | struct ufs_cylinder_group *ucg) | ||
140 | { | ||
141 | struct buffer_head *bh; | ||
142 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | ||
143 | sector_t beg = uspi->s_sbbase + | ||
144 | ufs_inotofsba(ucpi->c_cgx * uspi->s_ipg + | ||
145 | fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk)); | ||
146 | sector_t end = beg + uspi->s_fpb; | ||
147 | |||
148 | UFSD("ENTER cgno %d\n", ucpi->c_cgx); | ||
149 | |||
150 | for (; beg < end; ++beg) { | ||
151 | bh = sb_getblk(sb, beg); | ||
152 | lock_buffer(bh); | ||
153 | memset(bh->b_data, 0, sb->s_blocksize); | ||
154 | set_buffer_uptodate(bh); | ||
155 | mark_buffer_dirty(bh); | ||
156 | unlock_buffer(bh); | ||
157 | if (sb->s_flags & MS_SYNCHRONOUS) | ||
158 | sync_dirty_buffer(bh); | ||
159 | brelse(bh); | ||
160 | } | ||
161 | |||
162 | fs32_add(sb, &ucg->cg_u.cg_u2.cg_initediblk, uspi->s_inopb); | ||
163 | ubh_mark_buffer_dirty(UCPI_UBH(ucpi)); | ||
164 | if (sb->s_flags & MS_SYNCHRONOUS) { | ||
165 | ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi)); | ||
166 | ubh_wait_on_buffer(UCPI_UBH(ucpi)); | ||
167 | } | ||
168 | |||
169 | UFSD("EXIT\n"); | ||
170 | } | ||
171 | |||
172 | /* | ||
129 | * There are two policies for allocating an inode. If the new inode is | 173 | * There are two policies for allocating an inode. If the new inode is |
130 | * a directory, then a forward search is made for a block group with both | 174 | * a directory, then a forward search is made for a block group with both |
131 | * free space and a low directory-to-inode ratio; if that fails, then of | 175 | * free space and a low directory-to-inode ratio; if that fails, then of |
@@ -146,6 +190,7 @@ struct inode * ufs_new_inode(struct inode * dir, int mode) | |||
146 | struct inode * inode; | 190 | struct inode * inode; |
147 | unsigned cg, bit, i, j, start; | 191 | unsigned cg, bit, i, j, start; |
148 | struct ufs_inode_info *ufsi; | 192 | struct ufs_inode_info *ufsi; |
193 | int err = -ENOSPC; | ||
149 | 194 | ||
150 | UFSD("ENTER\n"); | 195 | UFSD("ENTER\n"); |
151 | 196 | ||
@@ -198,13 +243,15 @@ struct inode * ufs_new_inode(struct inode * dir, int mode) | |||
198 | goto cg_found; | 243 | goto cg_found; |
199 | } | 244 | } |
200 | } | 245 | } |
201 | 246 | ||
202 | goto failed; | 247 | goto failed; |
203 | 248 | ||
204 | cg_found: | 249 | cg_found: |
205 | ucpi = ufs_load_cylinder (sb, cg); | 250 | ucpi = ufs_load_cylinder (sb, cg); |
206 | if (!ucpi) | 251 | if (!ucpi) { |
252 | err = -EIO; | ||
207 | goto failed; | 253 | goto failed; |
254 | } | ||
208 | ucg = ubh_get_ucg(UCPI_UBH(ucpi)); | 255 | ucg = ubh_get_ucg(UCPI_UBH(ucpi)); |
209 | if (!ufs_cg_chkmagic(sb, ucg)) | 256 | if (!ufs_cg_chkmagic(sb, ucg)) |
210 | ufs_panic (sb, "ufs_new_inode", "internal error, bad cg magic number"); | 257 | ufs_panic (sb, "ufs_new_inode", "internal error, bad cg magic number"); |
@@ -216,6 +263,7 @@ cg_found: | |||
216 | if (!(bit < start)) { | 263 | if (!(bit < start)) { |
217 | ufs_error (sb, "ufs_new_inode", | 264 | ufs_error (sb, "ufs_new_inode", |
218 | "cylinder group %u corrupted - error in inode bitmap\n", cg); | 265 | "cylinder group %u corrupted - error in inode bitmap\n", cg); |
266 | err = -EIO; | ||
219 | goto failed; | 267 | goto failed; |
220 | } | 268 | } |
221 | } | 269 | } |
@@ -224,9 +272,18 @@ cg_found: | |||
224 | ubh_setbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit); | 272 | ubh_setbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit); |
225 | else { | 273 | else { |
226 | ufs_panic (sb, "ufs_new_inode", "internal error"); | 274 | ufs_panic (sb, "ufs_new_inode", "internal error"); |
275 | err = -EIO; | ||
227 | goto failed; | 276 | goto failed; |
228 | } | 277 | } |
229 | 278 | ||
279 | if (uspi->fs_magic == UFS2_MAGIC) { | ||
280 | u32 initediblk = fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk); | ||
281 | |||
282 | if (bit + uspi->s_inopb > initediblk && | ||
283 | initediblk < fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_niblk)) | ||
284 | ufs2_init_inodes_chunk(sb, ucpi, ucg); | ||
285 | } | ||
286 | |||
230 | fs32_sub(sb, &ucg->cg_cs.cs_nifree, 1); | 287 | fs32_sub(sb, &ucg->cg_cs.cs_nifree, 1); |
231 | uspi->cs_total.cs_nifree--; | 288 | uspi->cs_total.cs_nifree--; |
232 | fs32_sub(sb, &sbi->fs_cs(cg).cs_nifree, 1); | 289 | fs32_sub(sb, &sbi->fs_cs(cg).cs_nifree, 1); |
@@ -236,7 +293,6 @@ cg_found: | |||
236 | uspi->cs_total.cs_ndir++; | 293 | uspi->cs_total.cs_ndir++; |
237 | fs32_add(sb, &sbi->fs_cs(cg).cs_ndir, 1); | 294 | fs32_add(sb, &sbi->fs_cs(cg).cs_ndir, 1); |
238 | } | 295 | } |
239 | |||
240 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); | 296 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); |
241 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); | 297 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); |
242 | if (sb->s_flags & MS_SYNCHRONOUS) { | 298 | if (sb->s_flags & MS_SYNCHRONOUS) { |
@@ -245,6 +301,7 @@ cg_found: | |||
245 | } | 301 | } |
246 | sb->s_dirt = 1; | 302 | sb->s_dirt = 1; |
247 | 303 | ||
304 | inode->i_ino = cg * uspi->s_ipg + bit; | ||
248 | inode->i_mode = mode; | 305 | inode->i_mode = mode; |
249 | inode->i_uid = current->fsuid; | 306 | inode->i_uid = current->fsuid; |
250 | if (dir->i_mode & S_ISGID) { | 307 | if (dir->i_mode & S_ISGID) { |
@@ -254,39 +311,72 @@ cg_found: | |||
254 | } else | 311 | } else |
255 | inode->i_gid = current->fsgid; | 312 | inode->i_gid = current->fsgid; |
256 | 313 | ||
257 | inode->i_ino = cg * uspi->s_ipg + bit; | ||
258 | inode->i_blocks = 0; | 314 | inode->i_blocks = 0; |
315 | inode->i_generation = 0; | ||
259 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; | 316 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; |
260 | ufsi->i_flags = UFS_I(dir)->i_flags; | 317 | ufsi->i_flags = UFS_I(dir)->i_flags; |
261 | ufsi->i_lastfrag = 0; | 318 | ufsi->i_lastfrag = 0; |
262 | ufsi->i_gen = 0; | ||
263 | ufsi->i_shadow = 0; | 319 | ufsi->i_shadow = 0; |
264 | ufsi->i_osync = 0; | 320 | ufsi->i_osync = 0; |
265 | ufsi->i_oeftflag = 0; | 321 | ufsi->i_oeftflag = 0; |
266 | ufsi->i_dir_start_lookup = 0; | 322 | ufsi->i_dir_start_lookup = 0; |
267 | memset(&ufsi->i_u1, 0, sizeof(ufsi->i_u1)); | 323 | memset(&ufsi->i_u1, 0, sizeof(ufsi->i_u1)); |
268 | |||
269 | insert_inode_hash(inode); | 324 | insert_inode_hash(inode); |
270 | mark_inode_dirty(inode); | 325 | mark_inode_dirty(inode); |
271 | 326 | ||
327 | if (uspi->fs_magic == UFS2_MAGIC) { | ||
328 | struct buffer_head *bh; | ||
329 | struct ufs2_inode *ufs2_inode; | ||
330 | |||
331 | /* | ||
332 | * setup birth date, we do it here because of there is no sense | ||
333 | * to hold it in struct ufs_inode_info, and lose 64 bit | ||
334 | */ | ||
335 | bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino)); | ||
336 | if (!bh) { | ||
337 | ufs_warning(sb, "ufs_read_inode", | ||
338 | "unable to read inode %lu\n", | ||
339 | inode->i_ino); | ||
340 | err = -EIO; | ||
341 | goto fail_remove_inode; | ||
342 | } | ||
343 | lock_buffer(bh); | ||
344 | ufs2_inode = (struct ufs2_inode *)bh->b_data; | ||
345 | ufs2_inode += ufs_inotofsbo(inode->i_ino); | ||
346 | ufs2_inode->ui_birthtime.tv_sec = | ||
347 | cpu_to_fs32(sb, CURRENT_TIME_SEC.tv_sec); | ||
348 | ufs2_inode->ui_birthtime.tv_usec = 0; | ||
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 | |||
272 | unlock_super (sb); | 356 | unlock_super (sb); |
273 | 357 | ||
274 | if (DQUOT_ALLOC_INODE(inode)) { | 358 | if (DQUOT_ALLOC_INODE(inode)) { |
275 | DQUOT_DROP(inode); | 359 | DQUOT_DROP(inode); |
276 | inode->i_flags |= S_NOQUOTA; | 360 | err = -EDQUOT; |
277 | inode->i_nlink = 0; | 361 | goto fail_without_unlock; |
278 | iput(inode); | ||
279 | return ERR_PTR(-EDQUOT); | ||
280 | } | 362 | } |
281 | 363 | ||
282 | UFSD("allocating inode %lu\n", inode->i_ino); | 364 | UFSD("allocating inode %lu\n", inode->i_ino); |
283 | UFSD("EXIT\n"); | 365 | UFSD("EXIT\n"); |
284 | return inode; | 366 | return inode; |
285 | 367 | ||
368 | fail_remove_inode: | ||
369 | unlock_super(sb); | ||
370 | fail_without_unlock: | ||
371 | inode->i_flags |= S_NOQUOTA; | ||
372 | inode->i_nlink = 0; | ||
373 | iput(inode); | ||
374 | UFSD("EXIT (FAILED): err %d\n", err); | ||
375 | return ERR_PTR(err); | ||
286 | failed: | 376 | failed: |
287 | unlock_super (sb); | 377 | unlock_super (sb); |
288 | make_bad_inode(inode); | 378 | make_bad_inode(inode); |
289 | iput (inode); | 379 | iput (inode); |
290 | UFSD("EXIT (FAILED)\n"); | 380 | UFSD("EXIT (FAILED): err %d\n", err); |
291 | return ERR_PTR(-ENOSPC); | 381 | return ERR_PTR(err); |
292 | } | 382 | } |