| Start/ | End/ | |||
| True | False | - | Line | Source |
| 1 | /* | |||
| 2 | * linux/fs/ext2/inode.c | |||
| 3 | * | |||
| 4 | * Copyright (C) 1992, 1993, 1994, 1995 | |||
| 5 | * Remy Card (card@masi.ibp.fr) | |||
| 6 | * Laboratoire MASI - Institut Blaise Pascal | |||
| 7 | * Universite Pierre et Marie Curie (Paris VI) | |||
| 8 | * | |||
| 9 | * from | |||
| 10 | * | |||
| 11 | * linux/fs/minix/inode.c | |||
| 12 | * | |||
| 13 | * Copyright (C) 1991, 1992 Linus Torvalds | |||
| 14 | * | |||
| 15 | * Goal-directed block allocation by Stephen Tweedie | |||
| 16 | * (sct@dcs.ed.ac.uk), 1993, 1998 | |||
| 17 | * Big-endian to little-endian byte-swapping/bitmaps by | |||
| 18 | * David S. Miller (davem@caip.rutgers.edu), 1995 | |||
| 19 | * 64-bit file support on 64-bit platforms by Jakub Jelinek | |||
| 20 | * (jj@sunsite.ms.mff.cuni.cz) | |||
| 21 | * | |||
| 22 | * Assorted race fixes, rewrite of ext2_get_block() by Al Viro, 2000 | |||
| 23 | */ | |||
| 24 | ||||
| 25 | #include <linux/smp_lock.h> | |||
| 26 | #include <linux/time.h> | |||
| 27 | #include <linux/highuid.h> | |||
| 28 | #include <linux/pagemap.h> | |||
| 29 | #include <linux/quotaops.h> | |||
| 30 | #include <linux/module.h> | |||
| 31 | #include <linux/writeback.h> | |||
| 32 | #include <linux/buffer_head.h> | |||
| 33 | #include <linux/mpage.h> | |||
| 34 | #include "ext2.h" | |||
| 35 | #include "acl.h" | |||
| 36 | #include "xip.h" | |||
| 37 | ||||
| 38 | MODULE_AUTHOR("Remy Card and others"); | |||
| 39 | MODULE_DESCRIPTION("Second Extended Filesystem"); | |||
| 40 | MODULE_LICENSE("GPL"); | |||
| 41 | ||||
| 42 | static int ext2_update_inode(struct inode * inode, int do_sync); | |||
| 43 | ||||
| 44 | /* | |||
| 45 | * Test whether an inode is a fast symlink. | |||
| 46 | */ | |||
| 0 | 0 | - | 47 | static inline int ext2_inode_is_fast_symlink(struct inode *inode) |
| 48 | { | |||
| 49 | int ea_blocks = EXT2_I(inode)->i_file_acl ? | |||
| 0 | 0 | - | 49 | ternary-?: EXT2_I ( inode ) -> i_file_acl |
| 50 | (inode->i_sb->s_blocksize >> 9) : 0; | |||
| 51 | ||||
| 52 | return (S_ISLNK(inode->i_mode) && | |||
| 0 | - | 53 | inode->i_blocks - ea_blocks == 0); | |
| 54 | } | |||
| 55 | ||||
| 56 | /* | |||
| 57 | * Called at each iput(). | |||
| 58 | * | |||
| 59 | * The inode may be "bad" if ext2_read_inode() saw an error from | |||
| 60 | * ext2_get_inode(), so we need to check that to avoid freeing random disk | |||
| 61 | * blocks. | |||
| 62 | */ | |||
| 0 | 0 | - | 63 | void ext2_put_inode(struct inode *inode) |
| 64 | { | |||
| 0 | 0 | - | 65 | if (!is_bad_inode(inode)) |
| 66 | ext2_discard_prealloc(inode); | |||
| 67 | } | |||
| 68 | ||||
| 69 | /* | |||
| 70 | * Called at the last iput() if i_nlink is zero. | |||
| 71 | */ | |||
| 0 | 0 | - | 72 | void ext2_delete_inode (struct inode * inode) |
| 73 | { | |||
| 74 | truncate_inode_pages(&inode->i_data, 0); | |||
| 75 | ||||
| 0 | 0 | - | 76 | if (is_bad_inode(inode)) |
| 0 | - | 77 | goto no_delete; | |
| 78 | EXT2_I(inode)->i_dtime = get_seconds(); | |||
| 79 | mark_inode_dirty(inode); | |||
| 80 | ext2_update_inode(inode, inode_needs_sync(inode)); | |||
| 81 | ||||
| 82 | inode->i_size = 0; | |||
| 0 | 0 | - | 83 | if (inode->i_blocks) |
| 84 | ext2_truncate (inode); | |||
| 85 | ext2_free_inode (inode); | |||
| 86 | ||||
| 0 | - | 87 | return; | |
| 88 | no_delete: | |||
| 89 | clear_inode(inode); /* We must guarantee clearing of inode... */ | |||
| 90 | } | |||
| 91 | ||||
| 0 | 0 | - | 92 | void ext2_discard_prealloc (struct inode * inode) |
| 93 | { | |||
| 94 | #ifdef EXT2_PREALLOCATE | |||
| 95 | struct ext2_inode_info *ei = EXT2_I(inode); | |||
| 96 | write_lock(&ei->i_meta_lock); | |||
| 96 | do | |||
| 0 | 0 | - | 96 | do-while (0) |
| 0 | 0 | - | 96 | do-while (0) |
| 0 | 0 | - | 97 | if (ei->i_prealloc_count) { |
| 98 | unsigned short total = ei->i_prealloc_count; | |||
| 99 | unsigned long block = ei->i_prealloc_block; | |||
| 100 | ei->i_prealloc_count = 0; | |||
| 101 | ei->i_prealloc_block = 0; | |||
| 102 | write_unlock(&ei->i_meta_lock); | |||
| 102 | do | |||
| 0 | 0 | - | 102 | do-while (0) |
| 0 | 0 | - | 102 | do-while (0) |
| 103 | ext2_free_blocks (inode, block, total); | |||
| 0 | - | 104 | return; | |
| 105 | } else | |||
| 106 | write_unlock(&ei->i_meta_lock); | |||
| 106 | do | |||
| 0 | 0 | - | 106 | do-while (0) |
| 0 | 0 | - | 106 | do-while (0) |
| 107 | #endif | |||
| 108 | } | |||
| 109 | ||||
| 0 | 0 | - | 110 | static int ext2_alloc_block (struct inode * inode, unsigned long goal, int *err) |
| 111 | { | |||
| 112 | #ifdef EXT2FS_DEBUG | |||
| 113 | static unsigned long alloc_hits, alloc_attempts; | |||
| 114 | #endif | |||
| 115 | unsigned long result; | |||
| 116 | ||||
| 117 | ||||
| 118 | #ifdef EXT2_PREALLOCATE | |||
| 119 | struct ext2_inode_info *ei = EXT2_I(inode); | |||
| 120 | write_lock(&ei->i_meta_lock); | |||
| 120 | do | |||
| 0 | 0 | - | 120 | do-while (0) |
| 0 | 0 | - | 120 | do-while (0) |
| 121 | if (ei->i_prealloc_count && | |||
| 0 | 0 | - | 122 | (goal == ei->i_prealloc_block || goal + 1 == ei->i_prealloc_block)) |
| 0 | - | 122 | T && (T || _) | |
| 0 | - | 122 | T && (F || T) | |
| 0 | - | 122 | T && (F || F) | |
| 0 | - | 122 | F && (_ || _) | |
| 123 | { | |||
| 124 | result = ei->i_prealloc_block++; | |||
| 125 | ei->i_prealloc_count--; | |||
| 126 | write_unlock(&ei->i_meta_lock); | |||
| 126 | do | |||
| 0 | 0 | - | 126 | do-while (0) |
| 0 | 0 | - | 126 | do-while (0) |
| 127 | ext2_debug ("preallocation hit (%lu/%lu).\n", | |||
| 128 | ++alloc_hits, ++alloc_attempts); | |||
| 129 | } else { | |||
| 130 | write_unlock(&ei->i_meta_lock); | |||
| 130 | do | |||
| 0 | 0 | - | 130 | do-while (0) |
| 0 | 0 | - | 130 | do-while (0) |
| 131 | ext2_discard_prealloc (inode); | |||
| 132 | ext2_debug ("preallocation miss (%lu/%lu).\n", | |||
| 133 | alloc_hits, ++alloc_attempts); | |||
| 0 | 0 | - | 134 | if (S_ISREG(inode->i_mode)) |
| 135 | result = ext2_new_block (inode, goal, | |||
| 136 | &ei->i_prealloc_count, | |||
| 137 | &ei->i_prealloc_block, err); | |||
| 138 | else | |||
| 139 | result = ext2_new_block(inode, goal, NULL, NULL, err); | |||
| 140 | } | |||
| 141 | #else | |||
| 142 | result = ext2_new_block (inode, goal, 0, 0, err); | |||
| 143 | #endif | |||
| 0 | - | 144 | return result; | |
| 145 | } | |||
| 146 | ||||
| 147 | typedef struct { | |||
| 148 | __le32 *p; | |||
| 149 | __le32 key; | |||
| 150 | struct buffer_head *bh; | |||
| 151 | } Indirect; | |||
| 152 | ||||
| 0 | 0 | - | 153 | static inline void add_chain(Indirect *p, struct buffer_head *bh, __le32 *v) |
| 154 | { | |||
| 155 | p->key = *(p->p = v); | |||
| 156 | p->bh = bh; | |||
| 157 | } | |||
| 158 | ||||
| 0 | 0 | - | 159 | static inline int verify_chain(Indirect *from, Indirect *to) |
| 160 | { | |||
| 0 | 0 | - | 161 | while (from <= to && from->key == *from->p) |
| 0 | - | 161 | T && T | |
| 0 | - | 161 | T && F | |
| 0 | - | 161 | F && _ | |
| 162 | from++; | |||
| 0 | - | 163 | return (from > to); | |
| 164 | } | |||
| 165 | ||||
| 166 | /** | |||
| 167 | * ext2_block_to_path - parse the block number into array of offsets | |||
| 168 | * @inode: inode in question (we are only interested in its superblock) | |||
| 169 | * @i_block: block number to be parsed | |||
| 170 | * @offsets: array to store the offsets in | |||
| 171 | * @boundary: set this non-zero if the referred-to block is likely to be | |||
| 172 | * followed (on disk) by an indirect block. | |||
| 173 | * To store the locations of file's data ext2 uses a data structure common | |||
| 174 | * for UNIX filesystems - tree of pointers anchored in the inode, with | |||
| 175 | * data blocks at leaves and indirect blocks in intermediate nodes. | |||
| 176 | * This function translates the block number into path in that tree - | |||
| 177 | * return value is the path length and @offsets[n] is the offset of | |||
| 178 | * pointer to (n+1)th node in the nth one. If @block is out of range | |||
| 179 | * (negative or too large) warning is printed and zero returned. | |||
| 180 | * | |||
| 181 | * Note: function doesn't find node addresses, so no IO is needed. All | |||
| 182 | * we need to know is the capacity of indirect blocks (taken from the | |||
| 183 | * inode->i_sb). | |||
| 184 | */ | |||
| 185 | ||||
| 186 | /* | |||
| 187 | * Portability note: the last comparison (check that we fit into triple | |||
| 188 | * indirect block) is spelled differently, because otherwise on an | |||
| 189 | * architecture with 32-bit longs and 8Kb pages we might get into trouble | |||
| 190 | * if our filesystem had 8Kb blocks. We might use long long, but that would | |||
| 191 | * kill us on x86. Oh, well, at least the sign propagation does not matter - | |||
| 192 | * i_block would have to be negative in the very beginning, so we would not | |||
| 193 | * get there at all. | |||
| 194 | */ | |||
| 195 | ||||
| 0 | 0 | - | 196 | static int ext2_block_to_path(struct inode *inode, |
| 197 | long i_block, int offsets[4], int *boundary) | |||
| 198 | { | |||
| 199 | int ptrs = EXT2_ADDR_PER_BLOCK(inode->i_sb); | |||
| 200 | int ptrs_bits = EXT2_ADDR_PER_BLOCK_BITS(inode->i_sb); | |||
| 201 | const long direct_blocks = EXT2_NDIR_BLOCKS, | |||
| 202 | indirect_blocks = ptrs, | |||
| 203 | double_blocks = (1 << (ptrs_bits * 2)); | |||
| 204 | int n = 0; | |||
| 205 | int final = 0; | |||
| 206 | ||||
| 0 | 0 | - | 207 | if (i_block < 0) { |
| 208 | ext2_warning (inode->i_sb, "ext2_block_to_path", "block < 0"); | |||
| 0 | 0 | - | 209 | } else if (i_block < direct_blocks) { |
| 210 | offsets[n++] = i_block; | |||
| 211 | final = direct_blocks; | |||
| 0 | 0 | - | 212 | } else if ( (i_block -= direct_blocks) < indirect_blocks) { |
| 213 | offsets[n++] = EXT2_IND_BLOCK; | |||
| 214 | offsets[n++] = i_block; | |||
| 215 | final = ptrs; | |||
| 0 | 0 | - | 216 | } else if ((i_block -= indirect_blocks) < double_blocks) { |
| 217 | offsets[n++] = EXT2_DIND_BLOCK; | |||
| 218 | offsets[n++] = i_block >> ptrs_bits; | |||
| 219 | offsets[n++] = i_block & (ptrs - 1); | |||
| 220 | final = ptrs; | |||
| 0 | 0 | - | 221 | } else if (((i_block -= double_blocks) >> (ptrs_bits * 2)) < ptrs) { |
| 222 | offsets[n++] = EXT2_TIND_BLOCK; | |||
| 223 | offsets[n++] = i_block >> (ptrs_bits * 2); | |||
| 224 | offsets[n++] = (i_block >> ptrs_bits) & (ptrs - 1); | |||
| 225 | offsets[n++] = i_block & (ptrs - 1); | |||
| 226 | final = ptrs; | |||
| 227 | } else { | |||
| 228 | ext2_warning (inode->i_sb, "ext2_block_to_path", "block > big"); | |||
| 229 | } | |||
| 0 | 0 | - | 230 | if (boundary) |
| 231 | *boundary = (i_block & (ptrs - 1)) == (final - 1); | |||
| 0 | - | 232 | return n; | |
| 233 | } | |||
| 234 | ||||
| 235 | /** | |||
| 236 | * ext2_get_branch - read the chain of indirect blocks leading to data | |||
| 237 | * @inode: inode in question | |||
| 238 | * @depth: depth of the chain (1 - direct pointer, etc.) | |||
| 239 | * @offsets: offsets of pointers in inode/indirect blocks | |||
| 240 | * @chain: place to store the result | |||
| 241 | * @err: here we store the error value | |||
| 242 | * | |||
| 243 | * Function fills the array of triples <key, p, bh> and returns %NULL | |||
| 244 | * if everything went OK or the pointer to the last filled triple | |||
| 245 | * (incomplete one) otherwise. Upon the return chain[i].key contains | |||
| 246 | * the number of (i+1)-th block in the chain (as it is stored in memory, | |||
| 247 | * i.e. little-endian 32-bit), chain[i].p contains the address of that | |||
| 248 | * number (it points into struct inode for i==0 and into the bh->b_data | |||
| 249 | * for i>0) and chain[i].bh points to the buffer_head of i-th indirect | |||
| 250 | * block for i>0 and NULL for i==0. In other words, it holds the block | |||
| 251 | * numbers of the chain, addresses they were taken from (and where we can | |||
| 252 | * verify that chain did not change) and buffer_heads hosting these | |||
| 253 | * numbers. | |||
| 254 | * | |||
| 255 | * Function stops when it stumbles upon zero pointer (absent block) | |||
| 256 | * (pointer to last triple returned, *@err == 0) | |||
| 257 | * or when it gets an IO error reading an indirect block | |||
| 258 | * (ditto, *@err == -EIO) | |||
| 259 | * or when it notices that chain had been changed while it was reading | |||
| 260 | * (ditto, *@err == -EAGAIN) | |||
| 261 | * or when it reads all @depth-1 indirect blocks successfully and finds | |||
| 262 | * the whole chain, all way to the data (returns %NULL, *err == 0). | |||
| 263 | */ | |||
| 0 | 0 | - | 264 | static Indirect *ext2_get_branch(struct inode *inode, |
| 265 | int depth, | |||
| 266 | int *offsets, | |||
| 267 | Indirect chain[4], | |||
| 268 | int *err) | |||
| 269 | { | |||
| 270 | struct super_block *sb = inode->i_sb; | |||
| 271 | Indirect *p = chain; | |||
| 272 | struct buffer_head *bh; | |||
| 273 | ||||
| 274 | *err = 0; | |||
| 275 | /* i_data is not going away, no lock needed */ | |||
| 276 | add_chain (chain, NULL, EXT2_I(inode)->i_data + *offsets); | |||
| 0 | 0 | - | 277 | if (!p->key) |
| 0 | - | 278 | goto no_block; | |
| 0 | 0 | - | 279 | while (--depth) { |
| 280 | bh = sb_bread(sb, le32_to_cpu(p->key)); | |||
| 0 | 0 | - | 281 | if (!bh) |
| 0 | - | 282 | goto failure; | |
| 283 | read_lock(&EXT2_I(inode)->i_meta_lock); | |||
| 283 | do | |||
| 0 | 0 | - | 283 | do-while (0) |
| 0 | 0 | - | 283 | do-while (0) |
| 0 | 0 | - | 284 | if (!verify_chain(chain, p)) |
| 0 | - | 285 | goto changed; | |
| 286 | add_chain(++p, bh, (__le32*)bh->b_data + *++offsets); | |||
| 287 | read_unlock(&EXT2_I(inode)->i_meta_lock); | |||
| 287 | do | |||
| 0 | 0 | - | 287 | do-while (0) |
| 0 | 0 | - | 287 | do-while (0) |
| 0 | 0 | - | 288 | if (!p->key) |
| 0 | - | 289 | goto no_block; | |
| 290 | } | |||
| 0 | - | 291 | return NULL; | |
| 292 | ||||
| 293 | changed: | |||
| 294 | read_unlock(&EXT2_I(inode)->i_meta_lock); | |||
| 294 | do | |||
| 0 | 0 | - | 294 | do-while (0) |
| 0 | 0 | - | 294 | do-while (0) |
| 295 | brelse(bh); | |||
| 296 | *err = -EAGAIN; | |||
| 0 | - | 297 | goto no_block; | |
| 298 | failure: | |||
| 299 | *err = -EIO; | |||
| 300 | no_block: | |||
| 0 | - | 301 | return p; | |
| 302 | } | |||
| 303 | ||||
| 304 | /** | |||
| 305 | * ext2_find_near - find a place for allocation with sufficient locality | |||
| 306 | * @inode: owner | |||
| 307 | * @ind: descriptor of indirect block. | |||
| 308 | * | |||
| 309 | * This function returns the prefered place for block allocation. | |||
| 310 | * It is used when heuristic for sequential allocation fails. | |||
| 311 | * Rules are: | |||
| 312 | * + if there is a block to the left of our position - allocate near it. | |||
| 313 | * + if pointer will live in indirect block - allocate near that block. | |||
| 314 | * + if pointer will live in inode - allocate in the same cylinder group. | |||
| 315 | * | |||
| 316 | * In the latter case we colour the starting block by the callers PID to | |||
| 317 | * prevent it from clashing with concurrent allocations for a different inode | |||
| 318 | * in the same block group. The PID is used here so that functionally related | |||
| 319 | * files will be close-by on-disk. | |||
| 320 | * | |||
| 321 | * Caller must make sure that @ind is valid and will stay that way. | |||
| 322 | */ | |||
| 323 | ||||
| 0 | 0 | - | 324 | static unsigned long ext2_find_near(struct inode *inode, Indirect *ind) |
| 325 | { | |||
| 326 | struct ext2_inode_info *ei = EXT2_I(inode); | |||
| 327 | __le32 *start = ind->bh ? (__le32 *) ind->bh->b_data : ei->i_data; | |||
| 0 | 0 | - | 327 | ternary-?: ind -> bh |
| 328 | __le32 *p; | |||
| 329 | unsigned long bg_start; | |||
| 330 | unsigned long colour; | |||
| 331 | ||||
| 332 | /* Try to find previous block */ | |||
| 0 | 0 | - | 333 | for (p = ind->p - 1; p >= start; p--) |
| 0 | 0 | - | 334 | if (*p) |
| 0 | - | 335 | return le32_to_cpu(*p); | |
| 336 | ||||
| 337 | /* No such thing, so let's try location of indirect block */ | |||
| 0 | 0 | - | 338 | if (ind->bh) |
| 0 | - | 339 | return ind->bh->b_blocknr; | |
| 340 | ||||
| 341 | /* | |||
| 342 | * It is going to be refered from inode itself? OK, just put it into | |||
| 343 | * the same cylinder group then. | |||
| 344 | */ | |||
| 345 | bg_start = (ei->i_block_group * EXT2_BLOCKS_PER_GROUP(inode->i_sb)) + | |||
| 346 | le32_to_cpu(EXT2_SB(inode->i_sb)->s_es->s_first_data_block); | |||
| 347 | colour = (current->pid % 16) * | |||
| 348 | (EXT2_BLOCKS_PER_GROUP(inode->i_sb) / 16); | |||
| 0 | - | 349 | return bg_start + colour; | |
| 350 | } | |||
| 351 | ||||
| 352 | /** | |||
| 353 | * ext2_find_goal - find a prefered place for allocation. | |||
| 354 | * @inode: owner | |||
| 355 | * @block: block we want | |||
| 356 | * @chain: chain of indirect blocks | |||
| 357 | * @partial: pointer to the last triple within a chain | |||
| 358 | * @goal: place to store the result. | |||
| 359 | * | |||
| 360 | * Normally this function find the prefered place for block allocation, | |||
| 361 | * stores it in *@goal and returns zero. If the branch had been changed | |||
| 362 | * under us we return -EAGAIN. | |||
| 363 | */ | |||
| 364 | ||||
| 0 | 0 | - | 365 | static inline int ext2_find_goal(struct inode *inode, |
| 366 | long block, | |||
| 367 | Indirect chain[4], | |||
| 368 | Indirect *partial, | |||
| 369 | unsigned long *goal) | |||
| 370 | { | |||
| 371 | struct ext2_inode_info *ei = EXT2_I(inode); | |||
| 372 | write_lock(&ei->i_meta_lock); | |||
| 372 | do | |||
| 0 | 0 | - | 372 | do-while (0) |
| 0 | 0 | - | 372 | do-while (0) |
| 0 | 0 | - | 373 | if ((block == ei->i_next_alloc_block + 1) && ei->i_next_alloc_goal) { |
| 0 | - | 373 | (T) && T | |
| 0 | - | 373 | (T) && F | |
| 0 | - | 373 | (F) && _ | |
| 374 | ei->i_next_alloc_block++; | |||
| 375 | ei->i_next_alloc_goal++; | |||
| 376 | } | |||
| 0 | 0 | - | 377 | if (verify_chain(chain, partial)) { |
| 378 | /* | |||
| 379 | * try the heuristic for sequential allocation, | |||
| 380 | * failing that at least try to get decent locality. | |||
| 381 | */ | |||
| 0 | 0 | - | 382 | if (block == ei->i_next_alloc_block) |
| 383 | *goal = ei->i_next_alloc_goal; | |||
| 0 | 0 | - | 384 | if (!*goal) |
| 385 | *goal = ext2_find_near(inode, partial); | |||
| 386 | write_unlock(&ei->i_meta_lock); | |||
| 386 | do | |||
| 0 | 0 | - | 386 | do-while (0) |
| 0 | 0 | - | 386 | do-while (0) |
| 0 | - | 387 | return 0; | |
| 388 | } | |||
| 389 | write_unlock(&ei->i_meta_lock); | |||
| 389 | do | |||
| 0 | 0 | - | 389 | do-while (0) |
| 0 | 0 | - | 389 | do-while (0) |
| 0 | - | 390 | return -EAGAIN; | |
| 391 | } | |||
| 392 | ||||
| 393 | /** | |||
| 394 | * ext2_alloc_branch - allocate and set up a chain of blocks. | |||
| 395 | * @inode: owner | |||
| 396 | * @num: depth of the chain (number of blocks to allocate) | |||
| 397 | * @offsets: offsets (in the blocks) to store the pointers to next. | |||
| 398 | * @branch: place to store the chain in. | |||
| 399 | * | |||
| 400 | * This function allocates @num blocks, zeroes out all but the last one, | |||
| 401 | * links them into chain and (if we are synchronous) writes them to disk. | |||
| 402 | * In other words, it prepares a branch that can be spliced onto the | |||
| 403 | * inode. It stores the information about that chain in the branch[], in | |||
| 404 | * the same format as ext2_get_branch() would do. We are calling it after | |||
| 405 | * we had read the existing part of chain and partial points to the last | |||
| 406 | * triple of that (one with zero ->key). Upon the exit we have the same | |||
| 407 | * picture as after the successful ext2_get_block(), excpet that in one | |||
| 408 | * place chain is disconnected - *branch->p is still zero (we did not | |||
| 409 | * set the last link), but branch->key contains the number that should | |||
| 410 | * be placed into *branch->p to fill that gap. | |||
| 411 | * | |||
| 412 | * If allocation fails we free all blocks we've allocated (and forget | |||
| 413 | * their buffer_heads) and return the error value the from failed | |||
| 414 | * ext2_alloc_block() (normally -ENOSPC). Otherwise we set the chain | |||
| 415 | * as described above and return 0. | |||
| 416 | */ | |||
| 417 | ||||
| 0 | 0 | - | 418 | static int ext2_alloc_branch(struct inode *inode, |
| 419 | int num, | |||
| 420 | unsigned long goal, | |||
| 421 | int *offsets, | |||
| 422 | Indirect *branch) | |||
| 423 | { | |||
| 424 | int blocksize = inode->i_sb->s_blocksize; | |||
| 425 | int n = 0; | |||
| 426 | int err; | |||
| 427 | int i; | |||
| 428 | int parent = ext2_alloc_block(inode, goal, &err); | |||
| 429 | ||||
| 430 | branch[0].key = cpu_to_le32(parent); | |||
| 0 | 0 | - | 431 | if (parent) for (n = 1; n < num; n++) { |
| 0 | 0 | - | 431 | for (;n < num;) |
| 432 | struct buffer_head *bh; | |||
| 433 | /* Allocate the next block */ | |||
| 434 | int nr = ext2_alloc_block(inode, parent, &err); | |||
| 0 | 0 | - | 435 | if (!nr) |
| 0 | - | 436 | break; | |
| 437 | branch[n].key = cpu_to_le32(nr); | |||
| 438 | /* | |||
| 439 | * Get buffer_head for parent block, zero it out and set | |||
| 440 | * the pointer to new one, then send parent to disk. | |||
| 441 | */ | |||
| 442 | bh = sb_getblk(inode->i_sb, parent); | |||
| 0 | 0 | - | 443 | if (!bh) { |
| 444 | err = -EIO; | |||
| 0 | - | 445 | break; | |
| 446 | } | |||
| 447 | lock_buffer(bh); | |||
| 448 | memset(bh->b_data, 0, blocksize); | |||
| 449 | branch[n].bh = bh; | |||
| 450 | branch[n].p = (__le32 *) bh->b_data + offsets[n]; | |||
| 451 | *branch[n].p = branch[n].key; | |||
| 452 | set_buffer_uptodate(bh); | |||
| 453 | unlock_buffer(bh); | |||
| 454 | mark_buffer_dirty_inode(bh, inode); | |||
| 455 | /* We used to sync bh here if IS_SYNC(inode). | |||
| 456 | * But we now rely upon generic_osync_inode() | |||
| 457 | * and b_inode_buffers. But not for directories. | |||
| 458 | */ | |||
| 0 | 0 | - | 459 | if (S_ISDIR(inode->i_mode) && IS_DIRSYNC(inode)) |
| 0 | - | 459 | (T) && ((T) || (_)) | |
| 0 | - | 459 | (T) && ((F) || (T)) | |
| 0 | - | 459 | (T) && ((F) || (F)) | |
| 0 | - | 459 | (F) && ((_) || (_)) | |
| 460 | sync_dirty_buffer(bh); | |||
| 461 | parent = nr; | |||
| 462 | } | |||
| 0 | 0 | - | 463 | if (n == num) |
| 0 | - | 464 | return 0; | |
| 465 | ||||