diff options
Diffstat (limited to 'fs/gfs2/bmap.c')
| -rw-r--r-- | fs/gfs2/bmap.c | 670 |
1 files changed, 375 insertions, 295 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index e9456ebd3bb6..c19184f2e70e 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | * keep it small. | 33 | * keep it small. |
| 34 | */ | 34 | */ |
| 35 | struct metapath { | 35 | struct metapath { |
| 36 | struct buffer_head *mp_bh[GFS2_MAX_META_HEIGHT]; | ||
| 36 | __u16 mp_list[GFS2_MAX_META_HEIGHT]; | 37 | __u16 mp_list[GFS2_MAX_META_HEIGHT]; |
| 37 | }; | 38 | }; |
| 38 | 39 | ||
| @@ -135,9 +136,10 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page) | |||
| 135 | /* Get a free block, fill it with the stuffed data, | 136 | /* Get a free block, fill it with the stuffed data, |
| 136 | and write it out to disk */ | 137 | and write it out to disk */ |
| 137 | 138 | ||
| 139 | unsigned int n = 1; | ||
| 140 | block = gfs2_alloc_block(ip, &n); | ||
| 138 | if (isdir) { | 141 | if (isdir) { |
| 139 | block = gfs2_alloc_meta(ip); | 142 | gfs2_trans_add_unrevoke(GFS2_SB(&ip->i_inode), block, 1); |
| 140 | |||
| 141 | error = gfs2_dir_get_new_buffer(ip, block, &bh); | 143 | error = gfs2_dir_get_new_buffer(ip, block, &bh); |
| 142 | if (error) | 144 | if (error) |
| 143 | goto out_brelse; | 145 | goto out_brelse; |
| @@ -145,8 +147,6 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page) | |||
| 145 | dibh, sizeof(struct gfs2_dinode)); | 147 | dibh, sizeof(struct gfs2_dinode)); |
| 146 | brelse(bh); | 148 | brelse(bh); |
| 147 | } else { | 149 | } else { |
| 148 | block = gfs2_alloc_data(ip); | ||
| 149 | |||
| 150 | error = gfs2_unstuffer_page(ip, dibh, block, page); | 150 | error = gfs2_unstuffer_page(ip, dibh, block, page); |
| 151 | if (error) | 151 | if (error) |
| 152 | goto out_brelse; | 152 | goto out_brelse; |
| @@ -161,12 +161,11 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page) | |||
| 161 | 161 | ||
| 162 | if (ip->i_di.di_size) { | 162 | if (ip->i_di.di_size) { |
| 163 | *(__be64 *)(di + 1) = cpu_to_be64(block); | 163 | *(__be64 *)(di + 1) = cpu_to_be64(block); |
| 164 | ip->i_di.di_blocks++; | 164 | gfs2_add_inode_blocks(&ip->i_inode, 1); |
| 165 | gfs2_set_inode_blocks(&ip->i_inode); | 165 | di->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode)); |
| 166 | di->di_blocks = cpu_to_be64(ip->i_di.di_blocks); | ||
| 167 | } | 166 | } |
| 168 | 167 | ||
| 169 | ip->i_di.di_height = 1; | 168 | ip->i_height = 1; |
| 170 | di->di_height = cpu_to_be16(1); | 169 | di->di_height = cpu_to_be16(1); |
| 171 | 170 | ||
| 172 | out_brelse: | 171 | out_brelse: |
| @@ -176,114 +175,13 @@ out: | |||
| 176 | return error; | 175 | return error; |
| 177 | } | 176 | } |
| 178 | 177 | ||
| 179 | /** | ||
| 180 | * calc_tree_height - Calculate the height of a metadata tree | ||
| 181 | * @ip: The GFS2 inode | ||
| 182 | * @size: The proposed size of the file | ||
| 183 | * | ||
| 184 | * Work out how tall a metadata tree needs to be in order to accommodate a | ||
| 185 | * file of a particular size. If size is less than the current size of | ||
| 186 | * the inode, then the current size of the inode is used instead of the | ||
| 187 | * supplied one. | ||
| 188 | * | ||
| 189 | * Returns: the height the tree should be | ||
| 190 | */ | ||
| 191 | |||
| 192 | static unsigned int calc_tree_height(struct gfs2_inode *ip, u64 size) | ||
| 193 | { | ||
| 194 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
| 195 | u64 *arr; | ||
| 196 | unsigned int max, height; | ||
| 197 | |||
| 198 | if (ip->i_di.di_size > size) | ||
| 199 | size = ip->i_di.di_size; | ||
| 200 | |||
| 201 | if (gfs2_is_dir(ip)) { | ||
| 202 | arr = sdp->sd_jheightsize; | ||
| 203 | max = sdp->sd_max_jheight; | ||
| 204 | } else { | ||
| 205 | arr = sdp->sd_heightsize; | ||
| 206 | max = sdp->sd_max_height; | ||
| 207 | } | ||
| 208 | |||
| 209 | for (height = 0; height < max; height++) | ||
| 210 | if (arr[height] >= size) | ||
| 211 | break; | ||
| 212 | |||
| 213 | return height; | ||
| 214 | } | ||
| 215 | |||
| 216 | /** | ||
| 217 | * build_height - Build a metadata tree of the requested height | ||
| 218 | * @ip: The GFS2 inode | ||
| 219 | * @height: The height to build to | ||
| 220 | * | ||
| 221 | * | ||
| 222 | * Returns: errno | ||
| 223 | */ | ||
| 224 | |||
| 225 | static int build_height(struct inode *inode, unsigned height) | ||
| 226 | { | ||
| 227 | struct gfs2_inode *ip = GFS2_I(inode); | ||
| 228 | unsigned new_height = height - ip->i_di.di_height; | ||
| 229 | struct buffer_head *dibh; | ||
| 230 | struct buffer_head *blocks[GFS2_MAX_META_HEIGHT]; | ||
| 231 | struct gfs2_dinode *di; | ||
| 232 | int error; | ||
| 233 | __be64 *bp; | ||
| 234 | u64 bn; | ||
| 235 | unsigned n; | ||
| 236 | |||
| 237 | if (height <= ip->i_di.di_height) | ||
| 238 | return 0; | ||
| 239 | |||
| 240 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
| 241 | if (error) | ||
| 242 | return error; | ||
| 243 | |||
| 244 | for(n = 0; n < new_height; n++) { | ||
| 245 | bn = gfs2_alloc_meta(ip); | ||
| 246 | blocks[n] = gfs2_meta_new(ip->i_gl, bn); | ||
| 247 | gfs2_trans_add_bh(ip->i_gl, blocks[n], 1); | ||
| 248 | } | ||
| 249 | |||
| 250 | n = 0; | ||
| 251 | bn = blocks[0]->b_blocknr; | ||
| 252 | if (new_height > 1) { | ||
| 253 | for(; n < new_height-1; n++) { | ||
| 254 | gfs2_metatype_set(blocks[n], GFS2_METATYPE_IN, | ||
| 255 | GFS2_FORMAT_IN); | ||
| 256 | gfs2_buffer_clear_tail(blocks[n], | ||
| 257 | sizeof(struct gfs2_meta_header)); | ||
| 258 | bp = (__be64 *)(blocks[n]->b_data + | ||
| 259 | sizeof(struct gfs2_meta_header)); | ||
| 260 | *bp = cpu_to_be64(blocks[n+1]->b_blocknr); | ||
| 261 | brelse(blocks[n]); | ||
| 262 | blocks[n] = NULL; | ||
| 263 | } | ||
| 264 | } | ||
| 265 | gfs2_metatype_set(blocks[n], GFS2_METATYPE_IN, GFS2_FORMAT_IN); | ||
| 266 | gfs2_buffer_copy_tail(blocks[n], sizeof(struct gfs2_meta_header), | ||
| 267 | dibh, sizeof(struct gfs2_dinode)); | ||
| 268 | brelse(blocks[n]); | ||
| 269 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
| 270 | di = (struct gfs2_dinode *)dibh->b_data; | ||
| 271 | gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); | ||
| 272 | *(__be64 *)(di + 1) = cpu_to_be64(bn); | ||
| 273 | ip->i_di.di_height += new_height; | ||
| 274 | ip->i_di.di_blocks += new_height; | ||
| 275 | gfs2_set_inode_blocks(&ip->i_inode); | ||
| 276 | di->di_height = cpu_to_be16(ip->i_di.di_height); | ||
| 277 | di->di_blocks = cpu_to_be64(ip->i_di.di_blocks); | ||
| 278 | brelse(dibh); | ||
| 279 | return error; | ||
| 280 | } | ||
| 281 | 178 | ||
| 282 | /** | 179 | /** |
| 283 | * find_metapath - Find path through the metadata tree | 180 | * find_metapath - Find path through the metadata tree |
| 284 | * @ip: The inode pointer | 181 | * @sdp: The superblock |
| 285 | * @mp: The metapath to return the result in | 182 | * @mp: The metapath to return the result in |
| 286 | * @block: The disk block to look up | 183 | * @block: The disk block to look up |
| 184 | * @height: The pre-calculated height of the metadata tree | ||
| 287 | * | 185 | * |
| 288 | * This routine returns a struct metapath structure that defines a path | 186 | * This routine returns a struct metapath structure that defines a path |
| 289 | * through the metadata of inode "ip" to get to block "block". | 187 | * through the metadata of inode "ip" to get to block "block". |
| @@ -338,21 +236,29 @@ static int build_height(struct inode *inode, unsigned height) | |||
| 338 | * | 236 | * |
| 339 | */ | 237 | */ |
| 340 | 238 | ||
| 341 | static void find_metapath(struct gfs2_inode *ip, u64 block, | 239 | static void find_metapath(const struct gfs2_sbd *sdp, u64 block, |
| 342 | struct metapath *mp) | 240 | struct metapath *mp, unsigned int height) |
| 343 | { | 241 | { |
| 344 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
| 345 | u64 b = block; | ||
| 346 | unsigned int i; | 242 | unsigned int i; |
| 347 | 243 | ||
| 348 | for (i = ip->i_di.di_height; i--;) | 244 | for (i = height; i--;) |
| 349 | mp->mp_list[i] = do_div(b, sdp->sd_inptrs); | 245 | mp->mp_list[i] = do_div(block, sdp->sd_inptrs); |
| 246 | |||
| 247 | } | ||
| 350 | 248 | ||
| 249 | static inline unsigned int zero_metapath_length(const struct metapath *mp, | ||
| 250 | unsigned height) | ||
| 251 | { | ||
| 252 | unsigned int i; | ||
| 253 | for (i = 0; i < height - 1; i++) { | ||
| 254 | if (mp->mp_list[i] != 0) | ||
| 255 | return i; | ||
| 256 | } | ||
| 257 | return height; | ||
| 351 | } | 258 | } |
| 352 | 259 | ||
| 353 | /** | 260 | /** |
| 354 | * metapointer - Return pointer to start of metadata in a buffer | 261 | * metapointer - Return pointer to start of metadata in a buffer |
| 355 | * @bh: The buffer | ||
| 356 | * @height: The metadata height (0 = dinode) | 262 | * @height: The metadata height (0 = dinode) |
| 357 | * @mp: The metapath | 263 | * @mp: The metapath |
| 358 | * | 264 | * |
| @@ -361,93 +267,302 @@ static void find_metapath(struct gfs2_inode *ip, u64 block, | |||
| 361 | * metadata tree. | 267 | * metadata tree. |
| 362 | */ | 268 | */ |
| 363 | 269 | ||
| 364 | static inline __be64 *metapointer(struct buffer_head *bh, int *boundary, | 270 | static inline __be64 *metapointer(unsigned int height, const struct metapath *mp) |
| 365 | unsigned int height, const struct metapath *mp) | ||
| 366 | { | 271 | { |
| 272 | struct buffer_head *bh = mp->mp_bh[height]; | ||
| 367 | unsigned int head_size = (height > 0) ? | 273 | unsigned int head_size = (height > 0) ? |
| 368 | sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_dinode); | 274 | sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_dinode); |
| 369 | __be64 *ptr; | 275 | return ((__be64 *)(bh->b_data + head_size)) + mp->mp_list[height]; |
| 370 | *boundary = 0; | ||
| 371 | ptr = ((__be64 *)(bh->b_data + head_size)) + mp->mp_list[height]; | ||
| 372 | if (ptr + 1 == (__be64 *)(bh->b_data + bh->b_size)) | ||
| 373 | *boundary = 1; | ||
| 374 | return ptr; | ||
| 375 | } | 276 | } |
| 376 | 277 | ||
| 377 | /** | 278 | /** |
| 378 | * lookup_block - Get the next metadata block in metadata tree | 279 | * lookup_metapath - Walk the metadata tree to a specific point |
| 379 | * @ip: The GFS2 inode | 280 | * @ip: The inode |
| 380 | * @bh: Buffer containing the pointers to metadata blocks | ||
| 381 | * @height: The height of the tree (0 = dinode) | ||
| 382 | * @mp: The metapath | 281 | * @mp: The metapath |
| 383 | * @create: Non-zero if we may create a new meatdata block | ||
| 384 | * @new: Used to indicate if we did create a new metadata block | ||
| 385 | * @block: the returned disk block number | ||
| 386 | * | 282 | * |
| 387 | * Given a metatree, complete to a particular height, checks to see if the next | 283 | * Assumes that the inode's buffer has already been looked up and |
| 388 | * height of the tree exists. If not the next height of the tree is created. | 284 | * hooked onto mp->mp_bh[0] and that the metapath has been initialised |
| 389 | * The block number of the next height of the metadata tree is returned. | 285 | * by find_metapath(). |
| 286 | * | ||
| 287 | * If this function encounters part of the tree which has not been | ||
| 288 | * allocated, it returns the current height of the tree at the point | ||
| 289 | * at which it found the unallocated block. Blocks which are found are | ||
| 290 | * added to the mp->mp_bh[] list. | ||
| 390 | * | 291 | * |
| 292 | * Returns: error or height of metadata tree | ||
| 391 | */ | 293 | */ |
| 392 | 294 | ||
| 393 | static int lookup_block(struct gfs2_inode *ip, struct buffer_head *bh, | 295 | static int lookup_metapath(struct gfs2_inode *ip, struct metapath *mp) |
| 394 | unsigned int height, struct metapath *mp, int create, | ||
| 395 | int *new, u64 *block) | ||
| 396 | { | 296 | { |
| 397 | int boundary; | 297 | unsigned int end_of_metadata = ip->i_height - 1; |
| 398 | __be64 *ptr = metapointer(bh, &boundary, height, mp); | 298 | unsigned int x; |
| 299 | __be64 *ptr; | ||
| 300 | u64 dblock; | ||
| 301 | int ret; | ||
| 399 | 302 | ||
| 400 | if (*ptr) { | 303 | for (x = 0; x < end_of_metadata; x++) { |
| 401 | *block = be64_to_cpu(*ptr); | 304 | ptr = metapointer(x, mp); |
| 402 | return boundary; | 305 | dblock = be64_to_cpu(*ptr); |
| 403 | } | 306 | if (!dblock) |
| 307 | return x + 1; | ||
| 404 | 308 | ||
| 405 | *block = 0; | 309 | ret = gfs2_meta_indirect_buffer(ip, x+1, dblock, 0, &mp->mp_bh[x+1]); |
| 310 | if (ret) | ||
| 311 | return ret; | ||
| 312 | } | ||
| 406 | 313 | ||
| 407 | if (!create) | 314 | return ip->i_height; |
| 408 | return 0; | 315 | } |
| 409 | 316 | ||
| 410 | if (height == ip->i_di.di_height - 1 && !gfs2_is_dir(ip)) | 317 | static inline void release_metapath(struct metapath *mp) |
| 411 | *block = gfs2_alloc_data(ip); | 318 | { |
| 412 | else | 319 | int i; |
| 413 | *block = gfs2_alloc_meta(ip); | ||
| 414 | 320 | ||
| 415 | gfs2_trans_add_bh(ip->i_gl, bh, 1); | 321 | for (i = 0; i < GFS2_MAX_META_HEIGHT; i++) { |
| 322 | if (mp->mp_bh[i] == NULL) | ||
| 323 | break; | ||
| 324 | brelse(mp->mp_bh[i]); | ||
| 325 | } | ||
| 326 | } | ||
| 416 | 327 | ||
| 417 | *ptr = cpu_to_be64(*block); | 328 | /** |
| 418 | ip->i_di.di_blocks++; | 329 | * gfs2_extent_length - Returns length of an extent of blocks |
| 419 | gfs2_set_inode_blocks(&ip->i_inode); | 330 | * @start: Start of the buffer |
| 331 | * @len: Length of the buffer in bytes | ||
| 332 | * @ptr: Current position in the buffer | ||
| 333 | * @limit: Max extent length to return (0 = unlimited) | ||
| 334 | * @eob: Set to 1 if we hit "end of block" | ||
| 335 | * | ||
| 336 | * If the first block is zero (unallocated) it will return the number of | ||
| 337 | * unallocated blocks in the extent, otherwise it will return the number | ||
| 338 | * of contiguous blocks in the extent. | ||
| 339 | * | ||
| 340 | * Returns: The length of the extent (minimum of one block) | ||
| 341 | */ | ||
| 420 | 342 | ||
| 421 | *new = 1; | 343 | static inline unsigned int gfs2_extent_length(void *start, unsigned int len, __be64 *ptr, unsigned limit, int *eob) |
| 422 | return 0; | 344 | { |
| 345 | const __be64 *end = (start + len); | ||
| 346 | const __be64 *first = ptr; | ||
| 347 | u64 d = be64_to_cpu(*ptr); | ||
| 348 | |||
| 349 | *eob = 0; | ||
| 350 | do { | ||
| 351 | ptr++; | ||
| 352 | if (ptr >= end) | ||
| 353 | break; | ||
| 354 | if (limit && --limit == 0) | ||
| 355 | break; | ||
| 356 | if (d) | ||
| 357 | d++; | ||
| 358 | } while(be64_to_cpu(*ptr) == d); | ||
| 359 | if (ptr >= end) | ||
| 360 | *eob = 1; | ||
| 361 | return (ptr - first); | ||
| 423 | } | 362 | } |
| 424 | 363 | ||
| 425 | static inline void bmap_lock(struct inode *inode, int create) | 364 | static inline void bmap_lock(struct gfs2_inode *ip, int create) |
| 426 | { | 365 | { |
| 427 | struct gfs2_inode *ip = GFS2_I(inode); | ||
| 428 | if (create) | 366 | if (create) |
| 429 | down_write(&ip->i_rw_mutex); | 367 | down_write(&ip->i_rw_mutex); |
| 430 | else | 368 | else |
| 431 | down_read(&ip->i_rw_mutex); | 369 | down_read(&ip->i_rw_mutex); |
| 432 | } | 370 | } |
| 433 | 371 | ||
| 434 | static inline void bmap_unlock(struct inode *inode, int create) | 372 | static inline void bmap_unlock(struct gfs2_inode *ip, int create) |
| 435 | { | 373 | { |
| 436 | struct gfs2_inode *ip = GFS2_I(inode); | ||
| 437 | if (create) | 374 | if (create) |
| 438 | up_write(&ip->i_rw_mutex); | 375 | up_write(&ip->i_rw_mutex); |
| 439 | else | 376 | else |
| 440 | up_read(&ip->i_rw_mutex); | 377 | up_read(&ip->i_rw_mutex); |
| 441 | } | 378 | } |
| 442 | 379 | ||
| 380 | static inline __be64 *gfs2_indirect_init(struct metapath *mp, | ||
| 381 | struct gfs2_glock *gl, unsigned int i, | ||
| 382 | unsigned offset, u64 bn) | ||
| 383 | { | ||
| 384 | __be64 *ptr = (__be64 *)(mp->mp_bh[i - 1]->b_data + | ||
| 385 | ((i > 1) ? sizeof(struct gfs2_meta_header) : | ||
| 386 | sizeof(struct gfs2_dinode))); | ||
| 387 | BUG_ON(i < 1); | ||
| 388 | BUG_ON(mp->mp_bh[i] != NULL); | ||
| 389 | mp->mp_bh[i] = gfs2_meta_new(gl, bn); | ||
| 390 | gfs2_trans_add_bh(gl, mp->mp_bh[i], 1); | ||
| 391 | gfs2_metatype_set(mp->mp_bh[i], GFS2_METATYPE_IN, GFS2_FORMAT_IN); | ||
| 392 | gfs2_buffer_clear_tail(mp->mp_bh[i], sizeof(struct gfs2_meta_header)); | ||
| 393 | ptr += offset; | ||
| 394 | *ptr = cpu_to_be64(bn); | ||
| 395 | return ptr; | ||
| 396 | } | ||
| 397 | |||
| 398 | enum alloc_state { | ||
| 399 | ALLOC_DATA = 0, | ||
| 400 | ALLOC_GROW_DEPTH = 1, | ||
| 401 | ALLOC_GROW_HEIGHT = 2, | ||
| 402 | /* ALLOC_UNSTUFF = 3, TBD and rather complicated */ | ||
| 403 | }; | ||
| 404 | |||
| 405 | /** | ||
| 406 | * gfs2_bmap_alloc - Build a metadata tree of the requested height | ||
| 407 | * @inode: The GFS2 inode | ||
| 408 | * @lblock: The logical starting block of the extent | ||
| 409 | * @bh_map: This is used to return the mapping details | ||
| 410 | * @mp: The metapath | ||
| 411 | * @sheight: The starting height (i.e. whats already mapped) | ||
| 412 | * @height: The height to build to | ||
| 413 | * @maxlen: The max number of data blocks to alloc | ||
| 414 | * | ||
| 415 | * In this routine we may have to alloc: | ||
| 416 | * i) Indirect blocks to grow the metadata tree height | ||
| 417 | * ii) Indirect blocks to fill in lower part of the metadata tree | ||
| 418 | * iii) Data blocks | ||
| 419 | * | ||
| 420 | * The function is in two parts. The first part works out the total | ||
| 421 | * number of blocks which we need. The second part does the actual | ||
| 422 | * allocation asking for an extent at a time (if enough contiguous free | ||
| 423 | * blocks are available, there will only be one request per bmap call) | ||
| 424 | * and uses the state machine to initialise the blocks in order. | ||
| 425 | * | ||
| 426 | * Returns: errno on error | ||
| 427 | */ | ||
| 428 | |||
| 429 | static int gfs2_bmap_alloc(struct inode *inode, const sector_t lblock, | ||
| 430 | struct buffer_head *bh_map, struct metapath *mp, | ||
| 431 | const unsigned int sheight, | ||
| 432 | const unsigned int height, | ||
| 433 | const unsigned int maxlen) | ||
| 434 | { | ||
| 435 | struct gfs2_inode *ip = GFS2_I(inode); | ||
| 436 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
| 437 | struct buffer_head *dibh = mp->mp_bh[0]; | ||
| 438 | u64 bn, dblock = 0; | ||
| 439 | unsigned n, i, blks, alloced = 0, iblks = 0, zmpl = 0; | ||
| 440 | unsigned dblks = 0; | ||
| 441 | unsigned ptrs_per_blk; | ||
| 442 | const unsigned end_of_metadata = height - 1; | ||
| 443 | int eob = 0; | ||
| 444 | enum alloc_state state; | ||
| 445 | __be64 *ptr; | ||
| 446 | __be64 zero_bn = 0; | ||
| 447 | |||
| 448 | BUG_ON(sheight < 1); | ||
| 449 | BUG_ON(dibh == NULL); | ||
| 450 | |||
| 451 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
| 452 | |||
| 453 | if (height == sheight) { | ||
| 454 | struct buffer_head *bh; | ||
| 455 | /* Bottom indirect block exists, find unalloced extent size */ | ||
| 456 | ptr = metapointer(end_of_metadata, mp); | ||
| 457 | bh = mp->mp_bh[end_of_metadata]; | ||
| 458 | dblks = gfs2_extent_length(bh->b_data, bh->b_size, ptr, maxlen, | ||
| 459 | &eob); | ||
| 460 | BUG_ON(dblks < 1); | ||
| 461 | state = ALLOC_DATA; | ||
| 462 | } else { | ||
| 463 | /* Need to allocate indirect blocks */ | ||
| 464 | ptrs_per_blk = height > 1 ? sdp->sd_inptrs : sdp->sd_diptrs; | ||
| 465 | dblks = min(maxlen, ptrs_per_blk - mp->mp_list[end_of_metadata]); | ||
| 466 | if (height == ip->i_height) { | ||
| 467 | /* Writing into existing tree, extend tree down */ | ||
| 468 | iblks = height - sheight; | ||
| 469 | state = ALLOC_GROW_DEPTH; | ||
| 470 | } else { | ||
| 471 | /* Building up tree height */ | ||
| 472 | state = ALLOC_GROW_HEIGHT; | ||
| 473 | iblks = height - ip->i_height; | ||
| 474 | zmpl = zero_metapath_length(mp, height); | ||
| 475 | iblks -= zmpl; | ||
| 476 | iblks += height; | ||
| 477 | } | ||
| 478 | } | ||
| 479 | |||
| 480 | /* start of the second part of the function (state machine) */ | ||
| 481 | |||
| 482 | blks = dblks + iblks; | ||
| 483 | i = sheight; | ||
| 484 | do { | ||
| 485 | n = blks - alloced; | ||
| 486 | bn = gfs2_alloc_block(ip, &n); | ||
| 487 | alloced += n; | ||
| 488 | if (state != ALLOC_DATA || gfs2_is_jdata(ip)) | ||
| 489 | gfs2_trans_add_unrevoke(sdp, bn, n); | ||
| 490 | switch (state) { | ||
| 491 | /* Growing height of tree */ | ||
| 492 | case ALLOC_GROW_HEIGHT: | ||
| 493 | if (i == 1) { | ||
| 494 | ptr = (__be64 *)(dibh->b_data + | ||
| 495 | sizeof(struct gfs2_dinode)); | ||
| 496 | zero_bn = *ptr; | ||
| 497 | } | ||
| 498 | for (; i - 1 < height - ip->i_height && n > 0; i++, n--) | ||
| 499 | gfs2_indirect_init(mp, ip->i_gl, i, 0, bn++); | ||
| 500 | if (i - 1 == height - ip->i_height) { | ||
| 501 | i--; | ||
| 502 | gfs2_buffer_copy_tail(mp->mp_bh[i], | ||
| 503 | sizeof(struct gfs2_meta_header), | ||
| 504 | dibh, sizeof(struct gfs2_dinode)); | ||
| 505 | gfs2_buffer_clear_tail(dibh, | ||
| 506 | sizeof(struct gfs2_dinode) + | ||
| 507 | sizeof(__be64)); | ||
| 508 | ptr = (__be64 *)(mp->mp_bh[i]->b_data + | ||
| 509 | sizeof(struct gfs2_meta_header)); | ||
| 510 | *ptr = zero_bn; | ||
| 511 | state = ALLOC_GROW_DEPTH; | ||
| 512 | for(i = zmpl; i < height; i++) { | ||
| 513 | if (mp->mp_bh[i] == NULL) | ||
| 514 | break; | ||
| 515 | brelse(mp->mp_bh[i]); | ||
| 516 | mp->mp_bh[i] = NULL; | ||
| 517 | } | ||
| 518 | i = zmpl; | ||
| 519 | } | ||
| 520 | if (n == 0) | ||
| 521 | break; | ||
| 522 | /* Branching from existing tree */ | ||
| 523 | case ALLOC_GROW_DEPTH: | ||
| 524 | if (i > 1 && i < height) | ||
| 525 | gfs2_trans_add_bh(ip->i_gl, mp->mp_bh[i-1], 1); | ||
| 526 | for (; i < height && n > 0; i++, n--) | ||
| 527 | gfs2_indirect_init(mp, ip->i_gl, i, | ||
| 528 | mp->mp_list[i-1], bn++); | ||
| 529 | if (i == height) | ||
| 530 | state = ALLOC_DATA; | ||
| 531 | if (n == 0) | ||
| 532 | break; | ||
| 533 | /* Tree complete, adding data blocks */ | ||
| 534 | case ALLOC_DATA: | ||
| 535 | BUG_ON(n > dblks); | ||
| 536 | BUG_ON(mp->mp_bh[end_of_metadata] == NULL); | ||
| 537 | gfs2_trans_add_bh(ip->i_gl, mp->mp_bh[end_of_metadata], 1); | ||
| 538 | dblks = n; | ||
| 539 | ptr = metapointer(end_of_metadata, mp); | ||
| 540 | dblock = bn; | ||
| 541 | while (n-- > 0) | ||
| 542 | *ptr++ = cpu_to_be64(bn++); | ||
| 543 | break; | ||
| 544 | } | ||
| 545 | } while (state != ALLOC_DATA); | ||
| 546 | |||
| 547 | ip->i_height = height; | ||
| 548 | gfs2_add_inode_blocks(&ip->i_inode, alloced); | ||
| 549 | gfs2_dinode_out(ip, mp->mp_bh[0]->b_data); | ||
| 550 | map_bh(bh_map, inode->i_sb, dblock); | ||
| 551 | bh_map->b_size = dblks << inode->i_blkbits; | ||
| 552 | set_buffer_new(bh_map); | ||
| 553 | return 0; | ||
| 554 | } | ||
| 555 | |||
| 443 | /** | 556 | /** |
| 444 | * gfs2_block_map - Map a block from an inode to a disk block | 557 | * gfs2_block_map - Map a block from an inode to a disk block |
| 445 | * @inode: The inode | 558 | * @inode: The inode |
| 446 | * @lblock: The logical block number | 559 | * @lblock: The logical block number |
| 447 | * @bh_map: The bh to be mapped | 560 | * @bh_map: The bh to be mapped |
| 561 | * @create: True if its ok to alloc blocks to satify the request | ||
| 448 | * | 562 | * |
| 449 | * Find the block number on the current device which corresponds to an | 563 | * Sets buffer_mapped() if successful, sets buffer_boundary() if a |
| 450 | * inode's block. If the block had to be created, "new" will be set. | 564 | * read of metadata will be required before the next block can be |
| 565 | * mapped. Sets buffer_new() if new blocks were allocated. | ||
| 451 | * | 566 | * |
| 452 | * Returns: errno | 567 | * Returns: errno |
| 453 | */ | 568 | */ |
| @@ -457,97 +572,78 @@ int gfs2_block_map(struct inode *inode, sector_t lblock, | |||
| 457 | { | 572 | { |
| 458 | struct gfs2_inode *ip = GFS2_I(inode); | 573 | struct gfs2_inode *ip = GFS2_I(inode); |
| 459 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 574 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
| 460 | struct buffer_head *bh; | 575 | unsigned int bsize = sdp->sd_sb.sb_bsize; |
| 461 | unsigned int bsize; | 576 | const unsigned int maxlen = bh_map->b_size >> inode->i_blkbits; |
| 462 | unsigned int height; | 577 | const u64 *arr = sdp->sd_heightsize; |
| 463 | unsigned int end_of_metadata; | 578 | __be64 *ptr; |
| 464 | unsigned int x; | ||
| 465 | int error = 0; | ||
| 466 | int new = 0; | ||
| 467 | u64 dblock = 0; | ||
| 468 | int boundary; | ||
| 469 | unsigned int maxlen = bh_map->b_size >> inode->i_blkbits; | ||
| 470 | struct metapath mp; | ||
| 471 | u64 size; | 579 | u64 size; |
| 472 | struct buffer_head *dibh = NULL; | 580 | struct metapath mp; |
| 581 | int ret; | ||
| 582 | int eob; | ||
| 583 | unsigned int len; | ||
| 584 | struct buffer_head *bh; | ||
| 585 | u8 height; | ||
| 473 | 586 | ||
| 474 | BUG_ON(maxlen == 0); | 587 | BUG_ON(maxlen == 0); |
| 475 | 588 | ||
| 476 | if (gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip))) | 589 | memset(mp.mp_bh, 0, sizeof(mp.mp_bh)); |
| 477 | return 0; | 590 | bmap_lock(ip, create); |
| 478 | |||
| 479 | bmap_lock(inode, create); | ||
| 480 | clear_buffer_mapped(bh_map); | 591 | clear_buffer_mapped(bh_map); |
| 481 | clear_buffer_new(bh_map); | 592 | clear_buffer_new(bh_map); |
| 482 | clear_buffer_boundary(bh_map); | 593 | clear_buffer_boundary(bh_map); |
| 483 | bsize = gfs2_is_dir(ip) ? sdp->sd_jbsize : sdp->sd_sb.sb_bsize; | 594 | if (gfs2_is_dir(ip)) { |
| 484 | size = (lblock + 1) * bsize; | 595 | bsize = sdp->sd_jbsize; |
| 485 | 596 | arr = sdp->sd_jheightsize; | |
| 486 | if (size > ip->i_di.di_size) { | ||
| 487 | height = calc_tree_height(ip, size); | ||
| 488 | if (ip->i_di.di_height < height) { | ||
| 489 | if (!create) | ||
| 490 | goto out_ok; | ||
| 491 | |||
| 492 | error = build_height(inode, height); | ||
| 493 | if (error) | ||
| 494 | goto out_fail; | ||
| 495 | } | ||
| 496 | } | 597 | } |
| 497 | 598 | ||
| 498 | find_metapath(ip, lblock, &mp); | 599 | ret = gfs2_meta_inode_buffer(ip, &mp.mp_bh[0]); |
| 499 | end_of_metadata = ip->i_di.di_height - 1; | 600 | if (ret) |
| 500 | error = gfs2_meta_inode_buffer(ip, &bh); | 601 | goto out; |
| 501 | if (error) | ||
| 502 | goto out_fail; | ||
| 503 | dibh = bh; | ||
| 504 | get_bh(dibh); | ||
| 505 | 602 | ||
| 506 | for (x = 0; x < end_of_metadata; x++) { | 603 | height = ip->i_height; |
| 507 | lookup_block(ip, bh, x, &mp, create, &new, &dblock); | 604 | size = (lblock + 1) * bsize; |
| 508 | brelse(bh); | 605 | while (size > arr[height]) |
| 509 | if (!dblock) | 606 | height++; |
| 510 | goto out_ok; | 607 | find_metapath(sdp, lblock, &mp, height); |
| 608 | ret = 1; | ||
| 609 | if (height > ip->i_height || gfs2_is_stuffed(ip)) | ||
| 610 | goto do_alloc; | ||
| 611 | ret = lookup_metapath(ip, &mp); | ||
| 612 | if (ret < 0) | ||
| 613 | goto out; | ||
| 614 | if (ret != ip->i_height) | ||
| 615 | goto do_alloc; | ||
| 616 | ptr = metapointer(ip->i_height - 1, &mp); | ||
| 617 | if (*ptr == 0) | ||
| 618 | goto do_alloc; | ||
| 619 | map_bh(bh_map, inode->i_sb, be64_to_cpu(*ptr)); | ||
| 620 | bh = mp.mp_bh[ip->i_height - 1]; | ||
| 621 | len = gfs2_extent_length(bh->b_data, bh->b_size, ptr, maxlen, &eob); | ||
| 622 | bh_map->b_size = (len << inode->i_blkbits); | ||
| 623 | if (eob) | ||
| 624 | set_buffer_boundary(bh_map); | ||
| 625 | ret = 0; | ||
| 626 | out: | ||
| 627 | release_metapath(&mp); | ||
| 628 | bmap_unlock(ip, create); | ||
| 629 | return ret; | ||
| 511 | 630 | ||
| 512 | error = gfs2_meta_indirect_buffer(ip, x+1, dblock, new, &bh); | 631 | do_alloc: |
| 513 | if (error) | 632 | /* All allocations are done here, firstly check create flag */ |
| 514 | goto out_fail; | 633 | if (!create) { |
| 634 | BUG_ON(gfs2_is_stuffed(ip)); | ||
| 635 | ret = 0; | ||
| 636 | goto out; | ||
| 515 | } | 637 | } |
| 516 | 638 | ||
| 517 | boundary = lookup_block(ip, bh, end_of_metadata, &mp, create, &new, &dblock); | 639 | /* At this point ret is the tree depth of already allocated blocks */ |
| 518 | if (dblock) { | 640 | ret = gfs2_bmap_alloc(inode, lblock, bh_map, &mp, ret, height, maxlen); |
| 519 | map_bh(bh_map, inode->i_sb, dblock); | 641 | goto out; |
| 520 | if (boundary) | ||
| 521 | set_buffer_boundary(bh_map); | ||
| 522 | if (new) { | ||
| 523 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
| 524 | gfs2_dinode_out(ip, dibh->b_data); | ||
| 525 | set_buffer_new(bh_map); | ||
| 526 | goto out_brelse; | ||
| 527 | } | ||
| 528 | while(--maxlen && !buffer_boundary(bh_map)) { | ||
| 529 | u64 eblock; | ||
| 530 | |||
| 531 | mp.mp_list[end_of_metadata]++; | ||
| 532 | boundary = lookup_block(ip, bh, end_of_metadata, &mp, 0, &new, &eblock); | ||
| 533 | if (eblock != ++dblock) | ||
| 534 | break; | ||
| 535 | bh_map->b_size += (1 << inode->i_blkbits); | ||
| 536 | if (boundary) | ||
| 537 | set_buffer_boundary(bh_map); | ||
| 538 | } | ||
| 539 | } | ||
| 540 | out_brelse: | ||
| 541 | brelse(bh); | ||
| 542 | out_ok: | ||
| 543 | error = 0; | ||
| 544 | out_fail: | ||
| 545 | if (dibh) | ||
| 546 | brelse(dibh); | ||
| 547 | bmap_unlock(inode, create); | ||
| 548 | return error; | ||
| 549 | } | 642 | } |
| 550 | 643 | ||
| 644 | /* | ||
| 645 | * Deprecated: do not use in new code | ||
| 646 | */ | ||
| 551 | int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen) | 647 | int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsigned *extlen) |
| 552 | { | 648 | { |
| 553 | struct buffer_head bh = { .b_state = 0, .b_blocknr = 0 }; | 649 | struct buffer_head bh = { .b_state = 0, .b_blocknr = 0 }; |
| @@ -558,7 +654,7 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi | |||
| 558 | BUG_ON(!dblock); | 654 | BUG_ON(!dblock); |
| 559 | BUG_ON(!new); | 655 | BUG_ON(!new); |
| 560 | 656 | ||
| 561 | bh.b_size = 1 << (inode->i_blkbits + 5); | 657 | bh.b_size = 1 << (inode->i_blkbits + (create ? 0 : 5)); |
| 562 | ret = gfs2_block_map(inode, lblock, &bh, create); | 658 | ret = gfs2_block_map(inode, lblock, &bh, create); |
| 563 | *extlen = bh.b_size >> inode->i_blkbits; | 659 | *extlen = bh.b_size >> inode->i_blkbits; |
| 564 | *dblock = bh.b_blocknr; | 660 | *dblock = bh.b_blocknr; |
| @@ -621,7 +717,7 @@ static int recursive_scan(struct gfs2_inode *ip, struct buffer_head *dibh, | |||
| 621 | if (error) | 717 | if (error) |
| 622 | goto out; | 718 | goto out; |
| 623 | 719 | ||
| 624 | if (height < ip->i_di.di_height - 1) | 720 | if (height < ip->i_height - 1) |
| 625 | for (; top < bottom; top++, first = 0) { | 721 | for (; top < bottom; top++, first = 0) { |
| 626 | if (!*top) | 722 | if (!*top) |
| 627 | continue; | 723 | continue; |
| @@ -679,7 +775,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, | |||
| 679 | sm->sm_first = 0; | 775 | sm->sm_first = 0; |
| 680 | } | 776 | } |
| 681 | 777 | ||
| 682 | metadata = (height != ip->i_di.di_height - 1); | 778 | metadata = (height != ip->i_height - 1); |
| 683 | if (metadata) | 779 | if (metadata) |
| 684 | revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs; | 780 | revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs; |
| 685 | 781 | ||
| @@ -713,7 +809,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, | |||
| 713 | else | 809 | else |
| 714 | goto out; /* Nothing to do */ | 810 | goto out; /* Nothing to do */ |
| 715 | 811 | ||
| 716 | gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE, 0); | 812 | gfs2_rlist_alloc(&rlist, LM_ST_EXCLUSIVE); |
| 717 | 813 | ||
| 718 | for (x = 0; x < rlist.rl_rgrps; x++) { | 814 | for (x = 0; x < rlist.rl_rgrps; x++) { |
| 719 | struct gfs2_rgrpd *rgd; | 815 | struct gfs2_rgrpd *rgd; |
| @@ -760,10 +856,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh, | |||
| 760 | } | 856 | } |
| 761 | 857 | ||
| 762 | *p = 0; | 858 | *p = 0; |
| 763 | if (!ip->i_di.di_blocks) | 859 | gfs2_add_inode_blocks(&ip->i_inode, -1); |
| 764 | gfs2_consist_inode(ip); | ||
| 765 | ip->i_di.di_blocks--; | ||
| 766 | gfs2_set_inode_blocks(&ip->i_inode); | ||
| 767 | } | 860 | } |
| 768 | if (bstart) { | 861 | if (bstart) { |
| 769 | if (metadata) | 862 | if (metadata) |
| @@ -804,19 +897,16 @@ static int do_grow(struct gfs2_inode *ip, u64 size) | |||
| 804 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 897 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
| 805 | struct gfs2_alloc *al; | 898 | struct gfs2_alloc *al; |
| 806 | struct buffer_head *dibh; | 899 | struct buffer_head *dibh; |
| 807 | unsigned int h; | ||
| 808 | int error; | 900 | int error; |
| 809 | 901 | ||
| 810 | al = gfs2_alloc_get(ip); | 902 | al = gfs2_alloc_get(ip); |
| 903 | if (!al) | ||
| 904 | return -ENOMEM; | ||
| 811 | 905 | ||
| 812 | error = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); | 906 | error = gfs2_quota_lock_check(ip); |
| 813 | if (error) | 907 | if (error) |
| 814 | goto out; | 908 | goto out; |
| 815 | 909 | ||
| 816 | error = gfs2_quota_check(ip, ip->i_inode.i_uid, ip->i_inode.i_gid); | ||
| 817 | if (error) | ||
| 818 | goto out_gunlock_q; | ||
| 819 | |||
| 820 | al->al_requested = sdp->sd_max_height + RES_DATA; | 910 | al->al_requested = sdp->sd_max_height + RES_DATA; |
| 821 | 911 | ||
| 822 | error = gfs2_inplace_reserve(ip); | 912 | error = gfs2_inplace_reserve(ip); |
| @@ -829,34 +919,25 @@ static int do_grow(struct gfs2_inode *ip, u64 size) | |||
| 829 | if (error) | 919 | if (error) |
| 830 | goto out_ipres; | 920 | goto out_ipres; |
| 831 | 921 | ||
| 922 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
| 923 | if (error) | ||
| 924 | goto out_end_trans; | ||
| 925 | |||
| 832 | if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) { | 926 | if (size > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) { |
| 833 | if (gfs2_is_stuffed(ip)) { | 927 | if (gfs2_is_stuffed(ip)) { |
| 834 | error = gfs2_unstuff_dinode(ip, NULL); | 928 | error = gfs2_unstuff_dinode(ip, NULL); |
| 835 | if (error) | 929 | if (error) |
| 836 | goto out_end_trans; | 930 | goto out_brelse; |
| 837 | } | ||
| 838 | |||
| 839 | h = calc_tree_height(ip, size); | ||
| 840 | if (ip->i_di.di_height < h) { | ||
| 841 | down_write(&ip->i_rw_mutex); | ||
| 842 | error = build_height(&ip->i_inode, h); | ||
| 843 | up_write(&ip->i_rw_mutex); | ||
| 844 | if (error) | ||
| 845 | goto out_end_trans; | ||
| 846 | } | 931 | } |
| 847 | } | 932 | } |
| 848 | 933 | ||
| 849 | ip->i_di.di_size = size; | 934 | ip->i_di.di_size = size; |
| 850 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; | 935 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; |
| 851 | |||
| 852 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
| 853 | if (error) | ||
| 854 | goto out_end_trans; | ||
| 855 | |||
| 856 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 936 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
| 857 | gfs2_dinode_out(ip, dibh->b_data); | 937 | gfs2_dinode_out(ip, dibh->b_data); |
| 858 | brelse(dibh); | ||
| 859 | 938 | ||
| 939 | out_brelse: | ||
| 940 | brelse(dibh); | ||
| 860 | out_end_trans: | 941 | out_end_trans: |
| 861 | gfs2_trans_end(sdp); | 942 | gfs2_trans_end(sdp); |
| 862 | out_ipres: | 943 | out_ipres: |
| @@ -986,7 +1067,8 @@ out: | |||
| 986 | 1067 | ||
| 987 | static int trunc_dealloc(struct gfs2_inode *ip, u64 size) | 1068 | static int trunc_dealloc(struct gfs2_inode *ip, u64 size) |
| 988 | { | 1069 | { |
| 989 | unsigned int height = ip->i_di.di_height; | 1070 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
| 1071 | unsigned int height = ip->i_height; | ||
| 990 | u64 lblock; | 1072 | u64 lblock; |
| 991 | struct metapath mp; | 1073 | struct metapath mp; |
| 992 | int error; | 1074 | int error; |
| @@ -994,10 +1076,11 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 size) | |||
| 994 | if (!size) | 1076 | if (!size) |
| 995 | lblock = 0; | 1077 | lblock = 0; |
| 996 | else | 1078 | else |
| 997 | lblock = (size - 1) >> GFS2_SB(&ip->i_inode)->sd_sb.sb_bsize_shift; | 1079 | lblock = (size - 1) >> sdp->sd_sb.sb_bsize_shift; |
| 998 | 1080 | ||
| 999 | find_metapath(ip, lblock, &mp); | 1081 | find_metapath(sdp, lblock, &mp, ip->i_height); |
| 1000 | gfs2_alloc_get(ip); | 1082 | if (!gfs2_alloc_get(ip)) |
| 1083 | return -ENOMEM; | ||
| 1001 | 1084 | ||
| 1002 | error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); | 1085 | error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); |
| 1003 | if (error) | 1086 | if (error) |
| @@ -1037,10 +1120,8 @@ static int trunc_end(struct gfs2_inode *ip) | |||
| 1037 | goto out; | 1120 | goto out; |
| 1038 | 1121 | ||
| 1039 | if (!ip->i_di.di_size) { | 1122 | if (!ip->i_di.di_size) { |
| 1040 | ip->i_di.di_height = 0; | 1123 | ip->i_height = 0; |
| 1041 | ip->i_di.di_goal_meta = | 1124 | ip->i_goal = ip->i_no_addr; |
| 1042 | ip->i_di.di_goal_data = | ||
| 1043 | ip->i_no_addr; | ||
| 1044 | gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); | 1125 | gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); |
| 1045 | } | 1126 | } |
| 1046 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; | 1127 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; |
| @@ -1197,10 +1278,9 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | |||
| 1197 | unsigned int len, int *alloc_required) | 1278 | unsigned int len, int *alloc_required) |
| 1198 | { | 1279 | { |
| 1199 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1280 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
| 1200 | u64 lblock, lblock_stop, dblock; | 1281 | struct buffer_head bh; |
| 1201 | u32 extlen; | 1282 | unsigned int shift; |
| 1202 | int new = 0; | 1283 | u64 lblock, lblock_stop, size; |
| 1203 | int error = 0; | ||
| 1204 | 1284 | ||
| 1205 | *alloc_required = 0; | 1285 | *alloc_required = 0; |
| 1206 | 1286 | ||
| @@ -1214,6 +1294,8 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | |||
| 1214 | return 0; | 1294 | return 0; |
| 1215 | } | 1295 | } |
| 1216 | 1296 | ||
| 1297 | *alloc_required = 1; | ||
| 1298 | shift = sdp->sd_sb.sb_bsize_shift; | ||
| 1217 | if (gfs2_is_dir(ip)) { | 1299 | if (gfs2_is_dir(ip)) { |
| 1218 | unsigned int bsize = sdp->sd_jbsize; | 1300 | unsigned int bsize = sdp->sd_jbsize; |
| 1219 | lblock = offset; | 1301 | lblock = offset; |
| @@ -1221,27 +1303,25 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | |||
| 1221 | lblock_stop = offset + len + bsize - 1; | 1303 | lblock_stop = offset + len + bsize - 1; |
| 1222 | do_div(lblock_stop, bsize); | 1304 | do_div(lblock_stop, bsize); |
| 1223 | } else { | 1305 | } else { |
| 1224 | unsigned int shift = sdp->sd_sb.sb_bsize_shift; | ||
| 1225 | u64 end_of_file = (ip->i_di.di_size + sdp->sd_sb.sb_bsize - 1) >> shift; | 1306 | u64 end_of_file = (ip->i_di.di_size + sdp->sd_sb.sb_bsize - 1) >> shift; |
| 1226 | lblock = offset >> shift; | 1307 | lblock = offset >> shift; |
| 1227 | lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift; | 1308 | lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift; |
| 1228 | if (lblock_stop > end_of_file) { | 1309 | if (lblock_stop > end_of_file) |
| 1229 | *alloc_required = 1; | ||
| 1230 | return 0; | 1310 | return 0; |
| 1231 | } | ||
| 1232 | } | 1311 | } |
| 1233 | 1312 | ||
| 1234 | for (; lblock < lblock_stop; lblock += extlen) { | 1313 | size = (lblock_stop - lblock) << shift; |
| 1235 | error = gfs2_extent_map(&ip->i_inode, lblock, &new, &dblock, &extlen); | 1314 | do { |
| 1236 | if (error) | 1315 | bh.b_state = 0; |
| 1237 | return error; | 1316 | bh.b_size = size; |
| 1238 | 1317 | gfs2_block_map(&ip->i_inode, lblock, &bh, 0); | |
| 1239 | if (!dblock) { | 1318 | if (!buffer_mapped(&bh)) |
| 1240 | *alloc_required = 1; | ||
| 1241 | return 0; | 1319 | return 0; |
| 1242 | } | 1320 | size -= bh.b_size; |
| 1243 | } | 1321 | lblock += (bh.b_size >> ip->i_inode.i_blkbits); |
| 1322 | } while(size > 0); | ||
| 1244 | 1323 | ||
| 1324 | *alloc_required = 0; | ||
| 1245 | return 0; | 1325 | return 0; |
| 1246 | } | 1326 | } |
| 1247 | 1327 | ||
