diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/9p/vfs_inode.c | 3 | ||||
| -rw-r--r-- | fs/dcache.c | 10 | ||||
| -rw-r--r-- | fs/exec.c | 2 | ||||
| -rw-r--r-- | fs/inotify_user.c | 27 | ||||
| -rw-r--r-- | fs/ramfs/file-nommu.c | 2 | ||||
| -rw-r--r-- | fs/ubifs/debug.c | 2 | ||||
| -rw-r--r-- | fs/ubifs/dir.c | 2 | ||||
| -rw-r--r-- | fs/ubifs/find.c | 1 | ||||
| -rw-r--r-- | fs/ubifs/gc.c | 14 | ||||
| -rw-r--r-- | fs/ubifs/super.c | 3 | ||||
| -rw-r--r-- | fs/ubifs/tnc.c | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_inode.c | 94 |
12 files changed, 47 insertions, 115 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index c95295c65045..e83aa5ebe861 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
| @@ -626,8 +626,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 626 | return NULL; | 626 | return NULL; |
| 627 | 627 | ||
| 628 | error: | 628 | error: |
| 629 | if (fid) | 629 | p9_client_clunk(fid); |
| 630 | p9_client_clunk(fid); | ||
| 631 | 630 | ||
| 632 | return ERR_PTR(result); | 631 | return ERR_PTR(result); |
| 633 | } | 632 | } |
diff --git a/fs/dcache.c b/fs/dcache.c index 80e93956aced..e7a1a99b7464 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -1395,6 +1395,10 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name) | |||
| 1395 | if (dentry->d_parent != parent) | 1395 | if (dentry->d_parent != parent) |
| 1396 | goto next; | 1396 | goto next; |
| 1397 | 1397 | ||
| 1398 | /* non-existing due to RCU? */ | ||
| 1399 | if (d_unhashed(dentry)) | ||
| 1400 | goto next; | ||
| 1401 | |||
| 1398 | /* | 1402 | /* |
| 1399 | * It is safe to compare names since d_move() cannot | 1403 | * It is safe to compare names since d_move() cannot |
| 1400 | * change the qstr (protected by d_lock). | 1404 | * change the qstr (protected by d_lock). |
| @@ -1410,10 +1414,8 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name) | |||
| 1410 | goto next; | 1414 | goto next; |
| 1411 | } | 1415 | } |
| 1412 | 1416 | ||
| 1413 | if (!d_unhashed(dentry)) { | 1417 | atomic_inc(&dentry->d_count); |
| 1414 | atomic_inc(&dentry->d_count); | 1418 | found = dentry; |
| 1415 | found = dentry; | ||
| 1416 | } | ||
| 1417 | spin_unlock(&dentry->d_lock); | 1419 | spin_unlock(&dentry->d_lock); |
| 1418 | break; | 1420 | break; |
| 1419 | next: | 1421 | next: |
| @@ -752,11 +752,11 @@ static int exec_mmap(struct mm_struct *mm) | |||
| 752 | tsk->active_mm = mm; | 752 | tsk->active_mm = mm; |
| 753 | activate_mm(active_mm, mm); | 753 | activate_mm(active_mm, mm); |
| 754 | task_unlock(tsk); | 754 | task_unlock(tsk); |
| 755 | mm_update_next_owner(old_mm); | ||
| 756 | arch_pick_mmap_layout(mm); | 755 | arch_pick_mmap_layout(mm); |
| 757 | if (old_mm) { | 756 | if (old_mm) { |
| 758 | up_read(&old_mm->mmap_sem); | 757 | up_read(&old_mm->mmap_sem); |
| 759 | BUG_ON(active_mm != old_mm); | 758 | BUG_ON(active_mm != old_mm); |
| 759 | mm_update_next_owner(old_mm); | ||
| 760 | mmput(old_mm); | 760 | mmput(old_mm); |
| 761 | return 0; | 761 | return 0; |
| 762 | } | 762 | } |
diff --git a/fs/inotify_user.c b/fs/inotify_user.c index 60249429a253..d85c7d931cdf 100644 --- a/fs/inotify_user.c +++ b/fs/inotify_user.c | |||
| @@ -323,7 +323,7 @@ out: | |||
| 323 | } | 323 | } |
| 324 | 324 | ||
| 325 | /* | 325 | /* |
| 326 | * remove_kevent - cleans up and ultimately frees the given kevent | 326 | * remove_kevent - cleans up the given kevent |
| 327 | * | 327 | * |
| 328 | * Caller must hold dev->ev_mutex. | 328 | * Caller must hold dev->ev_mutex. |
| 329 | */ | 329 | */ |
| @@ -334,7 +334,13 @@ static void remove_kevent(struct inotify_device *dev, | |||
| 334 | 334 | ||
| 335 | dev->event_count--; | 335 | dev->event_count--; |
| 336 | dev->queue_size -= sizeof(struct inotify_event) + kevent->event.len; | 336 | dev->queue_size -= sizeof(struct inotify_event) + kevent->event.len; |
| 337 | } | ||
| 337 | 338 | ||
| 339 | /* | ||
| 340 | * free_kevent - frees the given kevent. | ||
| 341 | */ | ||
| 342 | static void free_kevent(struct inotify_kernel_event *kevent) | ||
| 343 | { | ||
| 338 | kfree(kevent->name); | 344 | kfree(kevent->name); |
| 339 | kmem_cache_free(event_cachep, kevent); | 345 | kmem_cache_free(event_cachep, kevent); |
| 340 | } | 346 | } |
| @@ -350,6 +356,7 @@ static void inotify_dev_event_dequeue(struct inotify_device *dev) | |||
| 350 | struct inotify_kernel_event *kevent; | 356 | struct inotify_kernel_event *kevent; |
| 351 | kevent = inotify_dev_get_event(dev); | 357 | kevent = inotify_dev_get_event(dev); |
| 352 | remove_kevent(dev, kevent); | 358 | remove_kevent(dev, kevent); |
| 359 | free_kevent(kevent); | ||
| 353 | } | 360 | } |
| 354 | } | 361 | } |
| 355 | 362 | ||
| @@ -433,17 +440,15 @@ static ssize_t inotify_read(struct file *file, char __user *buf, | |||
| 433 | dev = file->private_data; | 440 | dev = file->private_data; |
| 434 | 441 | ||
| 435 | while (1) { | 442 | while (1) { |
| 436 | int events; | ||
| 437 | 443 | ||
| 438 | prepare_to_wait(&dev->wq, &wait, TASK_INTERRUPTIBLE); | 444 | prepare_to_wait(&dev->wq, &wait, TASK_INTERRUPTIBLE); |
| 439 | 445 | ||
| 440 | mutex_lock(&dev->ev_mutex); | 446 | mutex_lock(&dev->ev_mutex); |
| 441 | events = !list_empty(&dev->events); | 447 | if (!list_empty(&dev->events)) { |
| 442 | mutex_unlock(&dev->ev_mutex); | ||
| 443 | if (events) { | ||
| 444 | ret = 0; | 448 | ret = 0; |
| 445 | break; | 449 | break; |
| 446 | } | 450 | } |
| 451 | mutex_unlock(&dev->ev_mutex); | ||
| 447 | 452 | ||
| 448 | if (file->f_flags & O_NONBLOCK) { | 453 | if (file->f_flags & O_NONBLOCK) { |
| 449 | ret = -EAGAIN; | 454 | ret = -EAGAIN; |
| @@ -462,7 +467,6 @@ static ssize_t inotify_read(struct file *file, char __user *buf, | |||
| 462 | if (ret) | 467 | if (ret) |
| 463 | return ret; | 468 | return ret; |
| 464 | 469 | ||
| 465 | mutex_lock(&dev->ev_mutex); | ||
| 466 | while (1) { | 470 | while (1) { |
| 467 | struct inotify_kernel_event *kevent; | 471 | struct inotify_kernel_event *kevent; |
| 468 | 472 | ||
| @@ -481,6 +485,13 @@ static ssize_t inotify_read(struct file *file, char __user *buf, | |||
| 481 | } | 485 | } |
| 482 | break; | 486 | break; |
| 483 | } | 487 | } |
| 488 | remove_kevent(dev, kevent); | ||
| 489 | |||
| 490 | /* | ||
| 491 | * Must perform the copy_to_user outside the mutex in order | ||
| 492 | * to avoid a lock order reversal with mmap_sem. | ||
| 493 | */ | ||
| 494 | mutex_unlock(&dev->ev_mutex); | ||
| 484 | 495 | ||
| 485 | if (copy_to_user(buf, &kevent->event, event_size)) { | 496 | if (copy_to_user(buf, &kevent->event, event_size)) { |
| 486 | ret = -EFAULT; | 497 | ret = -EFAULT; |
| @@ -498,7 +509,9 @@ static ssize_t inotify_read(struct file *file, char __user *buf, | |||
| 498 | count -= kevent->event.len; | 509 | count -= kevent->event.len; |
| 499 | } | 510 | } |
| 500 | 511 | ||
| 501 | remove_kevent(dev, kevent); | 512 | free_kevent(kevent); |
| 513 | |||
| 514 | mutex_lock(&dev->ev_mutex); | ||
| 502 | } | 515 | } |
| 503 | mutex_unlock(&dev->ev_mutex); | 516 | mutex_unlock(&dev->ev_mutex); |
| 504 | 517 | ||
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index 52312ec93ff4..5145cb9125af 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c | |||
| @@ -58,7 +58,7 @@ const struct inode_operations ramfs_file_inode_operations = { | |||
| 58 | * size 0 on the assumption that it's going to be used for an mmap of shared | 58 | * size 0 on the assumption that it's going to be used for an mmap of shared |
| 59 | * memory | 59 | * memory |
| 60 | */ | 60 | */ |
| 61 | static int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) | 61 | int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) |
| 62 | { | 62 | { |
| 63 | struct pagevec lru_pvec; | 63 | struct pagevec lru_pvec; |
| 64 | unsigned long npages, xpages, loop, limit; | 64 | unsigned long npages, xpages, loop, limit; |
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index b9cb77473758..d7f7645779f2 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c | |||
| @@ -538,7 +538,7 @@ void dbg_dump_node(const struct ubifs_info *c, const void *node) | |||
| 538 | printk(KERN_DEBUG "\t%d orphan inode numbers:\n", n); | 538 | printk(KERN_DEBUG "\t%d orphan inode numbers:\n", n); |
| 539 | for (i = 0; i < n; i++) | 539 | for (i = 0; i < n; i++) |
| 540 | printk(KERN_DEBUG "\t ino %llu\n", | 540 | printk(KERN_DEBUG "\t ino %llu\n", |
| 541 | le64_to_cpu(orph->inos[i])); | 541 | (unsigned long long)le64_to_cpu(orph->inos[i])); |
| 542 | break; | 542 | break; |
| 543 | } | 543 | } |
| 544 | default: | 544 | default: |
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 2b267c9a1806..526c01ec8003 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c | |||
| @@ -426,7 +426,7 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) | |||
| 426 | 426 | ||
| 427 | while (1) { | 427 | while (1) { |
| 428 | dbg_gen("feed '%s', ino %llu, new f_pos %#x", | 428 | dbg_gen("feed '%s', ino %llu, new f_pos %#x", |
| 429 | dent->name, le64_to_cpu(dent->inum), | 429 | dent->name, (unsigned long long)le64_to_cpu(dent->inum), |
| 430 | key_hash_flash(c, &dent->key)); | 430 | key_hash_flash(c, &dent->key)); |
| 431 | ubifs_assert(dent->ch.sqnum > ubifs_inode(dir)->creat_sqnum); | 431 | ubifs_assert(dent->ch.sqnum > ubifs_inode(dir)->creat_sqnum); |
| 432 | 432 | ||
diff --git a/fs/ubifs/find.c b/fs/ubifs/find.c index e045c8b55423..47814cde2407 100644 --- a/fs/ubifs/find.c +++ b/fs/ubifs/find.c | |||
| @@ -507,7 +507,6 @@ int ubifs_find_free_space(struct ubifs_info *c, int min_space, int *free, | |||
| 507 | rsvd_idx_lebs = 0; | 507 | rsvd_idx_lebs = 0; |
| 508 | lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt - | 508 | lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt - |
| 509 | c->lst.taken_empty_lebs; | 509 | c->lst.taken_empty_lebs; |
| 510 | ubifs_assert(lebs + c->lst.idx_lebs >= c->min_idx_lebs); | ||
| 511 | if (rsvd_idx_lebs < lebs) | 510 | if (rsvd_idx_lebs < lebs) |
| 512 | /* | 511 | /* |
| 513 | * OK to allocate an empty LEB, but we still don't want to go | 512 | * OK to allocate an empty LEB, but we still don't want to go |
diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index 13f1019c859f..02aba36fe3d4 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c | |||
| @@ -334,15 +334,15 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp) | |||
| 334 | 334 | ||
| 335 | err = move_nodes(c, sleb); | 335 | err = move_nodes(c, sleb); |
| 336 | if (err) | 336 | if (err) |
| 337 | goto out; | 337 | goto out_inc_seq; |
| 338 | 338 | ||
| 339 | err = gc_sync_wbufs(c); | 339 | err = gc_sync_wbufs(c); |
| 340 | if (err) | 340 | if (err) |
| 341 | goto out; | 341 | goto out_inc_seq; |
| 342 | 342 | ||
| 343 | err = ubifs_change_one_lp(c, lnum, c->leb_size, 0, 0, 0, 0); | 343 | err = ubifs_change_one_lp(c, lnum, c->leb_size, 0, 0, 0, 0); |
| 344 | if (err) | 344 | if (err) |
| 345 | goto out; | 345 | goto out_inc_seq; |
| 346 | 346 | ||
| 347 | /* Allow for races with TNC */ | 347 | /* Allow for races with TNC */ |
| 348 | c->gced_lnum = lnum; | 348 | c->gced_lnum = lnum; |
| @@ -369,6 +369,14 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp) | |||
| 369 | out: | 369 | out: |
| 370 | ubifs_scan_destroy(sleb); | 370 | ubifs_scan_destroy(sleb); |
| 371 | return err; | 371 | return err; |
| 372 | |||
| 373 | out_inc_seq: | ||
| 374 | /* We may have moved at least some nodes so allow for races with TNC */ | ||
| 375 | c->gced_lnum = lnum; | ||
| 376 | smp_wmb(); | ||
| 377 | c->gc_seq += 1; | ||
| 378 | smp_wmb(); | ||
| 379 | goto out; | ||
| 372 | } | 380 | } |
| 373 | 381 | ||
| 374 | /** | 382 | /** |
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 7562464ac83f..3f4902060c7a 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
| @@ -1024,14 +1024,13 @@ static int mount_ubifs(struct ubifs_info *c) | |||
| 1024 | goto out_dereg; | 1024 | goto out_dereg; |
| 1025 | } | 1025 | } |
| 1026 | 1026 | ||
| 1027 | sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id); | ||
| 1027 | if (!mounted_read_only) { | 1028 | if (!mounted_read_only) { |
| 1028 | err = alloc_wbufs(c); | 1029 | err = alloc_wbufs(c); |
| 1029 | if (err) | 1030 | if (err) |
| 1030 | goto out_cbuf; | 1031 | goto out_cbuf; |
| 1031 | 1032 | ||
| 1032 | /* Create background thread */ | 1033 | /* Create background thread */ |
| 1033 | sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, | ||
| 1034 | c->vi.vol_id); | ||
| 1035 | c->bgt = kthread_create(ubifs_bg_thread, c, c->bgt_name); | 1034 | c->bgt = kthread_create(ubifs_bg_thread, c, c->bgt_name); |
| 1036 | if (!c->bgt) | 1035 | if (!c->bgt) |
| 1037 | c->bgt = ERR_PTR(-EINVAL); | 1036 | c->bgt = ERR_PTR(-EINVAL); |
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index 7da209ab9378..7634c5970887 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c | |||
| @@ -1476,7 +1476,7 @@ again: | |||
| 1476 | } | 1476 | } |
| 1477 | 1477 | ||
| 1478 | err = fallible_read_node(c, key, &zbr, node); | 1478 | err = fallible_read_node(c, key, &zbr, node); |
| 1479 | if (maybe_leb_gced(c, zbr.lnum, gc_seq1)) { | 1479 | if (err <= 0 || maybe_leb_gced(c, zbr.lnum, gc_seq1)) { |
| 1480 | /* | 1480 | /* |
| 1481 | * The node may have been GC'ed out from under us so try again | 1481 | * The node may have been GC'ed out from under us so try again |
| 1482 | * while keeping the TNC mutex locked. | 1482 | * while keeping the TNC mutex locked. |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 00e80df9dd9d..dbd9cef852ec 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
| @@ -4118,7 +4118,7 @@ xfs_iext_indirect_to_direct( | |||
| 4118 | ASSERT(nextents <= XFS_LINEAR_EXTS); | 4118 | ASSERT(nextents <= XFS_LINEAR_EXTS); |
| 4119 | size = nextents * sizeof(xfs_bmbt_rec_t); | 4119 | size = nextents * sizeof(xfs_bmbt_rec_t); |
| 4120 | 4120 | ||
| 4121 | xfs_iext_irec_compact_full(ifp); | 4121 | xfs_iext_irec_compact_pages(ifp); |
| 4122 | ASSERT(ifp->if_real_bytes == XFS_IEXT_BUFSZ); | 4122 | ASSERT(ifp->if_real_bytes == XFS_IEXT_BUFSZ); |
| 4123 | 4123 | ||
| 4124 | ep = ifp->if_u1.if_ext_irec->er_extbuf; | 4124 | ep = ifp->if_u1.if_ext_irec->er_extbuf; |
| @@ -4449,8 +4449,7 @@ xfs_iext_irec_remove( | |||
| 4449 | * compaction policy is as follows: | 4449 | * compaction policy is as follows: |
| 4450 | * | 4450 | * |
| 4451 | * Full Compaction: Extents fit into a single page (or inline buffer) | 4451 | * Full Compaction: Extents fit into a single page (or inline buffer) |
| 4452 | * Full Compaction: Extents occupy less than 10% of allocated space | 4452 | * Partial Compaction: Extents occupy less than 50% of allocated space |
| 4453 | * Partial Compaction: Extents occupy > 10% and < 50% of allocated space | ||
| 4454 | * No Compaction: Extents occupy at least 50% of allocated space | 4453 | * No Compaction: Extents occupy at least 50% of allocated space |
| 4455 | */ | 4454 | */ |
| 4456 | void | 4455 | void |
| @@ -4471,8 +4470,6 @@ xfs_iext_irec_compact( | |||
| 4471 | xfs_iext_direct_to_inline(ifp, nextents); | 4470 | xfs_iext_direct_to_inline(ifp, nextents); |
| 4472 | } else if (nextents <= XFS_LINEAR_EXTS) { | 4471 | } else if (nextents <= XFS_LINEAR_EXTS) { |
| 4473 | xfs_iext_indirect_to_direct(ifp); | 4472 | xfs_iext_indirect_to_direct(ifp); |
| 4474 | } else if (nextents < (nlists * XFS_LINEAR_EXTS) >> 3) { | ||
| 4475 | xfs_iext_irec_compact_full(ifp); | ||
| 4476 | } else if (nextents < (nlists * XFS_LINEAR_EXTS) >> 1) { | 4473 | } else if (nextents < (nlists * XFS_LINEAR_EXTS) >> 1) { |
| 4477 | xfs_iext_irec_compact_pages(ifp); | 4474 | xfs_iext_irec_compact_pages(ifp); |
| 4478 | } | 4475 | } |
| @@ -4496,7 +4493,7 @@ xfs_iext_irec_compact_pages( | |||
| 4496 | erp_next = erp + 1; | 4493 | erp_next = erp + 1; |
| 4497 | if (erp_next->er_extcount <= | 4494 | if (erp_next->er_extcount <= |
| 4498 | (XFS_LINEAR_EXTS - erp->er_extcount)) { | 4495 | (XFS_LINEAR_EXTS - erp->er_extcount)) { |
| 4499 | memmove(&erp->er_extbuf[erp->er_extcount], | 4496 | memcpy(&erp->er_extbuf[erp->er_extcount], |
| 4500 | erp_next->er_extbuf, erp_next->er_extcount * | 4497 | erp_next->er_extbuf, erp_next->er_extcount * |
| 4501 | sizeof(xfs_bmbt_rec_t)); | 4498 | sizeof(xfs_bmbt_rec_t)); |
| 4502 | erp->er_extcount += erp_next->er_extcount; | 4499 | erp->er_extcount += erp_next->er_extcount; |
| @@ -4516,91 +4513,6 @@ xfs_iext_irec_compact_pages( | |||
| 4516 | } | 4513 | } |
| 4517 | 4514 | ||
| 4518 | /* | 4515 | /* |
| 4519 | * Fully compact the extent records managed by the indirection array. | ||
| 4520 | */ | ||
| 4521 | void | ||
| 4522 | xfs_iext_irec_compact_full( | ||
| 4523 | xfs_ifork_t *ifp) /* inode fork pointer */ | ||
| 4524 | { | ||
| 4525 | xfs_bmbt_rec_host_t *ep, *ep_next; /* extent record pointers */ | ||
| 4526 | xfs_ext_irec_t *erp, *erp_next; /* extent irec pointers */ | ||
| 4527 | int erp_idx = 0; /* extent irec index */ | ||
| 4528 | int ext_avail; /* empty entries in ex list */ | ||
| 4529 | int ext_diff; /* number of exts to add */ | ||
| 4530 | int nlists; /* number of irec's (ex lists) */ | ||
| 4531 | |||
| 4532 | ASSERT(ifp->if_flags & XFS_IFEXTIREC); | ||
| 4533 | |||
| 4534 | nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; | ||
| 4535 | erp = ifp->if_u1.if_ext_irec; | ||
| 4536 | ep = &erp->er_extbuf[erp->er_extcount]; | ||
| 4537 | erp_next = erp + 1; | ||
| 4538 | ep_next = erp_next->er_extbuf; | ||
| 4539 | |||
| 4540 | while (erp_idx < nlists - 1) { | ||
| 4541 | /* | ||
| 4542 | * Check how many extent records are available in this irec. | ||
| 4543 | * If there is none skip the whole exercise. | ||
| 4544 | */ | ||
| 4545 | ext_avail = XFS_LINEAR_EXTS - erp->er_extcount; | ||
| 4546 | if (ext_avail) { | ||
| 4547 | |||
| 4548 | /* | ||
| 4549 | * Copy over as many as possible extent records into | ||
| 4550 | * the previous page. | ||
| 4551 | */ | ||
| 4552 | ext_diff = MIN(ext_avail, erp_next->er_extcount); | ||
| 4553 | memcpy(ep, ep_next, ext_diff * sizeof(xfs_bmbt_rec_t)); | ||
| 4554 | erp->er_extcount += ext_diff; | ||
| 4555 | erp_next->er_extcount -= ext_diff; | ||
| 4556 | |||
| 4557 | /* | ||
| 4558 | * If the next irec is empty now we can simply | ||
| 4559 | * remove it. | ||
| 4560 | */ | ||
| 4561 | if (erp_next->er_extcount == 0) { | ||
| 4562 | /* | ||
| 4563 | * Free page before removing extent record | ||
| 4564 | * so er_extoffs don't get modified in | ||
| 4565 | * xfs_iext_irec_remove. | ||
| 4566 | */ | ||
| 4567 | kmem_free(erp_next->er_extbuf); | ||
| 4568 | erp_next->er_extbuf = NULL; | ||
| 4569 | xfs_iext_irec_remove(ifp, erp_idx + 1); | ||
| 4570 | erp = &ifp->if_u1.if_ext_irec[erp_idx]; | ||
| 4571 | nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; | ||
| 4572 | |||
| 4573 | /* | ||
| 4574 | * If the next irec is not empty move up the content | ||
| 4575 | * that has not been copied to the previous page to | ||
| 4576 | * the beggining of this one. | ||
| 4577 | */ | ||
| 4578 | } else { | ||
| 4579 | memmove(erp_next->er_extbuf, &ep_next[ext_diff], | ||
| 4580 | erp_next->er_extcount * | ||
| 4581 | sizeof(xfs_bmbt_rec_t)); | ||
| 4582 | ep_next = erp_next->er_extbuf; | ||
| 4583 | memset(&ep_next[erp_next->er_extcount], 0, | ||
| 4584 | (XFS_LINEAR_EXTS - | ||
| 4585 | erp_next->er_extcount) * | ||
| 4586 | sizeof(xfs_bmbt_rec_t)); | ||
| 4587 | } | ||
| 4588 | } | ||
| 4589 | |||
| 4590 | if (erp->er_extcount == XFS_LINEAR_EXTS) { | ||
| 4591 | erp_idx++; | ||
| 4592 | if (erp_idx < nlists) | ||
| 4593 | erp = &ifp->if_u1.if_ext_irec[erp_idx]; | ||
| 4594 | else | ||
| 4595 | break; | ||
| 4596 | } | ||
| 4597 | ep = &erp->er_extbuf[erp->er_extcount]; | ||
| 4598 | erp_next = erp + 1; | ||
| 4599 | ep_next = erp_next->er_extbuf; | ||
| 4600 | } | ||
| 4601 | } | ||
| 4602 | |||
| 4603 | /* | ||
| 4604 | * This is called to update the er_extoff field in the indirection | 4516 | * This is called to update the er_extoff field in the indirection |
| 4605 | * array when extents have been added or removed from one of the | 4517 | * array when extents have been added or removed from one of the |
| 4606 | * extent lists. erp_idx contains the irec index to begin updating | 4518 | * extent lists. erp_idx contains the irec index to begin updating |
