diff options
Diffstat (limited to 'fs')
47 files changed, 447 insertions, 368 deletions
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 646337dc5201..529300327f45 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
| @@ -600,9 +600,6 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags) | |||
| 600 | 600 | ||
| 601 | /* lock down the parent dentry so we can peer at it */ | 601 | /* lock down the parent dentry so we can peer at it */ |
| 602 | parent = dget_parent(dentry); | 602 | parent = dget_parent(dentry); |
| 603 | if (!parent->d_inode) | ||
| 604 | goto out_bad; | ||
| 605 | |||
| 606 | dir = AFS_FS_I(parent->d_inode); | 603 | dir = AFS_FS_I(parent->d_inode); |
| 607 | 604 | ||
| 608 | /* validate the parent directory */ | 605 | /* validate the parent directory */ |
| @@ -167,10 +167,25 @@ static int __init aio_setup(void) | |||
| 167 | } | 167 | } |
| 168 | __initcall(aio_setup); | 168 | __initcall(aio_setup); |
| 169 | 169 | ||
| 170 | static void put_aio_ring_file(struct kioctx *ctx) | ||
| 171 | { | ||
| 172 | struct file *aio_ring_file = ctx->aio_ring_file; | ||
| 173 | if (aio_ring_file) { | ||
| 174 | truncate_setsize(aio_ring_file->f_inode, 0); | ||
| 175 | |||
| 176 | /* Prevent further access to the kioctx from migratepages */ | ||
| 177 | spin_lock(&aio_ring_file->f_inode->i_mapping->private_lock); | ||
| 178 | aio_ring_file->f_inode->i_mapping->private_data = NULL; | ||
| 179 | ctx->aio_ring_file = NULL; | ||
| 180 | spin_unlock(&aio_ring_file->f_inode->i_mapping->private_lock); | ||
| 181 | |||
| 182 | fput(aio_ring_file); | ||
| 183 | } | ||
| 184 | } | ||
| 185 | |||
| 170 | static void aio_free_ring(struct kioctx *ctx) | 186 | static void aio_free_ring(struct kioctx *ctx) |
| 171 | { | 187 | { |
| 172 | int i; | 188 | int i; |
| 173 | struct file *aio_ring_file = ctx->aio_ring_file; | ||
| 174 | 189 | ||
| 175 | for (i = 0; i < ctx->nr_pages; i++) { | 190 | for (i = 0; i < ctx->nr_pages; i++) { |
| 176 | pr_debug("pid(%d) [%d] page->count=%d\n", current->pid, i, | 191 | pr_debug("pid(%d) [%d] page->count=%d\n", current->pid, i, |
| @@ -178,14 +193,10 @@ static void aio_free_ring(struct kioctx *ctx) | |||
| 178 | put_page(ctx->ring_pages[i]); | 193 | put_page(ctx->ring_pages[i]); |
| 179 | } | 194 | } |
| 180 | 195 | ||
| 196 | put_aio_ring_file(ctx); | ||
| 197 | |||
| 181 | if (ctx->ring_pages && ctx->ring_pages != ctx->internal_pages) | 198 | if (ctx->ring_pages && ctx->ring_pages != ctx->internal_pages) |
| 182 | kfree(ctx->ring_pages); | 199 | kfree(ctx->ring_pages); |
| 183 | |||
| 184 | if (aio_ring_file) { | ||
| 185 | truncate_setsize(aio_ring_file->f_inode, 0); | ||
| 186 | fput(aio_ring_file); | ||
| 187 | ctx->aio_ring_file = NULL; | ||
| 188 | } | ||
| 189 | } | 200 | } |
| 190 | 201 | ||
| 191 | static int aio_ring_mmap(struct file *file, struct vm_area_struct *vma) | 202 | static int aio_ring_mmap(struct file *file, struct vm_area_struct *vma) |
| @@ -207,9 +218,8 @@ static int aio_set_page_dirty(struct page *page) | |||
| 207 | static int aio_migratepage(struct address_space *mapping, struct page *new, | 218 | static int aio_migratepage(struct address_space *mapping, struct page *new, |
| 208 | struct page *old, enum migrate_mode mode) | 219 | struct page *old, enum migrate_mode mode) |
| 209 | { | 220 | { |
| 210 | struct kioctx *ctx = mapping->private_data; | 221 | struct kioctx *ctx; |
| 211 | unsigned long flags; | 222 | unsigned long flags; |
| 212 | unsigned idx = old->index; | ||
| 213 | int rc; | 223 | int rc; |
| 214 | 224 | ||
| 215 | /* Writeback must be complete */ | 225 | /* Writeback must be complete */ |
| @@ -224,10 +234,23 @@ static int aio_migratepage(struct address_space *mapping, struct page *new, | |||
| 224 | 234 | ||
| 225 | get_page(new); | 235 | get_page(new); |
| 226 | 236 | ||
| 227 | spin_lock_irqsave(&ctx->completion_lock, flags); | 237 | /* We can potentially race against kioctx teardown here. Use the |
| 228 | migrate_page_copy(new, old); | 238 | * address_space's private data lock to protect the mapping's |
| 229 | ctx->ring_pages[idx] = new; | 239 | * private_data. |
| 230 | spin_unlock_irqrestore(&ctx->completion_lock, flags); | 240 | */ |
| 241 | spin_lock(&mapping->private_lock); | ||
| 242 | ctx = mapping->private_data; | ||
| 243 | if (ctx) { | ||
| 244 | pgoff_t idx; | ||
| 245 | spin_lock_irqsave(&ctx->completion_lock, flags); | ||
| 246 | migrate_page_copy(new, old); | ||
| 247 | idx = old->index; | ||
| 248 | if (idx < (pgoff_t)ctx->nr_pages) | ||
| 249 | ctx->ring_pages[idx] = new; | ||
| 250 | spin_unlock_irqrestore(&ctx->completion_lock, flags); | ||
| 251 | } else | ||
| 252 | rc = -EBUSY; | ||
| 253 | spin_unlock(&mapping->private_lock); | ||
| 231 | 254 | ||
| 232 | return rc; | 255 | return rc; |
| 233 | } | 256 | } |
| @@ -617,8 +640,7 @@ out_freepcpu: | |||
| 617 | out_freeref: | 640 | out_freeref: |
| 618 | free_percpu(ctx->users.pcpu_count); | 641 | free_percpu(ctx->users.pcpu_count); |
| 619 | out_freectx: | 642 | out_freectx: |
| 620 | if (ctx->aio_ring_file) | 643 | put_aio_ring_file(ctx); |
| 621 | fput(ctx->aio_ring_file); | ||
| 622 | kmem_cache_free(kioctx_cachep, ctx); | 644 | kmem_cache_free(kioctx_cachep, ctx); |
| 623 | pr_debug("error allocating ioctx %d\n", err); | 645 | pr_debug("error allocating ioctx %d\n", err); |
| 624 | return ERR_PTR(err); | 646 | return ERR_PTR(err); |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 100edcc5e312..4c94a79991bb 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
| @@ -1413,7 +1413,7 @@ static void fill_siginfo_note(struct memelfnote *note, user_siginfo_t *csigdata, | |||
| 1413 | * long file_ofs | 1413 | * long file_ofs |
| 1414 | * followed by COUNT filenames in ASCII: "FILE1" NUL "FILE2" NUL... | 1414 | * followed by COUNT filenames in ASCII: "FILE1" NUL "FILE2" NUL... |
| 1415 | */ | 1415 | */ |
| 1416 | static void fill_files_note(struct memelfnote *note) | 1416 | static int fill_files_note(struct memelfnote *note) |
| 1417 | { | 1417 | { |
| 1418 | struct vm_area_struct *vma; | 1418 | struct vm_area_struct *vma; |
| 1419 | unsigned count, size, names_ofs, remaining, n; | 1419 | unsigned count, size, names_ofs, remaining, n; |
| @@ -1428,11 +1428,11 @@ static void fill_files_note(struct memelfnote *note) | |||
| 1428 | names_ofs = (2 + 3 * count) * sizeof(data[0]); | 1428 | names_ofs = (2 + 3 * count) * sizeof(data[0]); |
| 1429 | alloc: | 1429 | alloc: |
| 1430 | if (size >= MAX_FILE_NOTE_SIZE) /* paranoia check */ | 1430 | if (size >= MAX_FILE_NOTE_SIZE) /* paranoia check */ |
| 1431 | goto err; | 1431 | return -EINVAL; |
| 1432 | size = round_up(size, PAGE_SIZE); | 1432 | size = round_up(size, PAGE_SIZE); |
| 1433 | data = vmalloc(size); | 1433 | data = vmalloc(size); |
| 1434 | if (!data) | 1434 | if (!data) |
| 1435 | goto err; | 1435 | return -ENOMEM; |
| 1436 | 1436 | ||
| 1437 | start_end_ofs = data + 2; | 1437 | start_end_ofs = data + 2; |
| 1438 | name_base = name_curpos = ((char *)data) + names_ofs; | 1438 | name_base = name_curpos = ((char *)data) + names_ofs; |
| @@ -1485,7 +1485,7 @@ static void fill_files_note(struct memelfnote *note) | |||
| 1485 | 1485 | ||
| 1486 | size = name_curpos - (char *)data; | 1486 | size = name_curpos - (char *)data; |
| 1487 | fill_note(note, "CORE", NT_FILE, size, data); | 1487 | fill_note(note, "CORE", NT_FILE, size, data); |
| 1488 | err: ; | 1488 | return 0; |
| 1489 | } | 1489 | } |
| 1490 | 1490 | ||
| 1491 | #ifdef CORE_DUMP_USE_REGSET | 1491 | #ifdef CORE_DUMP_USE_REGSET |
| @@ -1686,8 +1686,8 @@ static int fill_note_info(struct elfhdr *elf, int phdrs, | |||
| 1686 | fill_auxv_note(&info->auxv, current->mm); | 1686 | fill_auxv_note(&info->auxv, current->mm); |
| 1687 | info->size += notesize(&info->auxv); | 1687 | info->size += notesize(&info->auxv); |
| 1688 | 1688 | ||
| 1689 | fill_files_note(&info->files); | 1689 | if (fill_files_note(&info->files) == 0) |
| 1690 | info->size += notesize(&info->files); | 1690 | info->size += notesize(&info->files); |
| 1691 | 1691 | ||
| 1692 | return 1; | 1692 | return 1; |
| 1693 | } | 1693 | } |
| @@ -1719,7 +1719,8 @@ static int write_note_info(struct elf_note_info *info, | |||
| 1719 | return 0; | 1719 | return 0; |
| 1720 | if (first && !writenote(&info->auxv, file, foffset)) | 1720 | if (first && !writenote(&info->auxv, file, foffset)) |
| 1721 | return 0; | 1721 | return 0; |
| 1722 | if (first && !writenote(&info->files, file, foffset)) | 1722 | if (first && info->files.data && |
| 1723 | !writenote(&info->files, file, foffset)) | ||
| 1723 | return 0; | 1724 | return 0; |
| 1724 | 1725 | ||
| 1725 | for (i = 1; i < info->thread_notes; ++i) | 1726 | for (i = 1; i < info->thread_notes; ++i) |
| @@ -1806,6 +1807,7 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t) | |||
| 1806 | 1807 | ||
| 1807 | struct elf_note_info { | 1808 | struct elf_note_info { |
| 1808 | struct memelfnote *notes; | 1809 | struct memelfnote *notes; |
| 1810 | struct memelfnote *notes_files; | ||
| 1809 | struct elf_prstatus *prstatus; /* NT_PRSTATUS */ | 1811 | struct elf_prstatus *prstatus; /* NT_PRSTATUS */ |
| 1810 | struct elf_prpsinfo *psinfo; /* NT_PRPSINFO */ | 1812 | struct elf_prpsinfo *psinfo; /* NT_PRPSINFO */ |
| 1811 | struct list_head thread_list; | 1813 | struct list_head thread_list; |
| @@ -1896,9 +1898,12 @@ static int fill_note_info(struct elfhdr *elf, int phdrs, | |||
| 1896 | 1898 | ||
| 1897 | fill_siginfo_note(info->notes + 2, &info->csigdata, siginfo); | 1899 | fill_siginfo_note(info->notes + 2, &info->csigdata, siginfo); |
| 1898 | fill_auxv_note(info->notes + 3, current->mm); | 1900 | fill_auxv_note(info->notes + 3, current->mm); |
| 1899 | fill_files_note(info->notes + 4); | 1901 | info->numnote = 4; |
| 1900 | 1902 | ||
| 1901 | info->numnote = 5; | 1903 | if (fill_files_note(info->notes + info->numnote) == 0) { |
| 1904 | info->notes_files = info->notes + info->numnote; | ||
| 1905 | info->numnote++; | ||
| 1906 | } | ||
| 1902 | 1907 | ||
| 1903 | /* Try to dump the FPU. */ | 1908 | /* Try to dump the FPU. */ |
| 1904 | info->prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, regs, | 1909 | info->prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, regs, |
| @@ -1960,8 +1965,9 @@ static void free_note_info(struct elf_note_info *info) | |||
| 1960 | kfree(list_entry(tmp, struct elf_thread_status, list)); | 1965 | kfree(list_entry(tmp, struct elf_thread_status, list)); |
| 1961 | } | 1966 | } |
| 1962 | 1967 | ||
| 1963 | /* Free data allocated by fill_files_note(): */ | 1968 | /* Free data possibly allocated by fill_files_note(): */ |
| 1964 | vfree(info->notes[4].data); | 1969 | if (info->notes_files) |
| 1970 | vfree(info->notes_files->data); | ||
| 1965 | 1971 | ||
| 1966 | kfree(info->prstatus); | 1972 | kfree(info->prstatus); |
| 1967 | kfree(info->psinfo); | 1973 | kfree(info->psinfo); |
| @@ -2044,7 +2050,7 @@ static int elf_core_dump(struct coredump_params *cprm) | |||
| 2044 | struct vm_area_struct *vma, *gate_vma; | 2050 | struct vm_area_struct *vma, *gate_vma; |
| 2045 | struct elfhdr *elf = NULL; | 2051 | struct elfhdr *elf = NULL; |
| 2046 | loff_t offset = 0, dataoff, foffset; | 2052 | loff_t offset = 0, dataoff, foffset; |
| 2047 | struct elf_note_info info; | 2053 | struct elf_note_info info = { }; |
| 2048 | struct elf_phdr *phdr4note = NULL; | 2054 | struct elf_phdr *phdr4note = NULL; |
| 2049 | struct elf_shdr *shdr4extnum = NULL; | 2055 | struct elf_shdr *shdr4extnum = NULL; |
| 2050 | Elf_Half e_phnum; | 2056 | Elf_Half e_phnum; |
| @@ -917,8 +917,8 @@ void bio_copy_data(struct bio *dst, struct bio *src) | |||
| 917 | src_p = kmap_atomic(src_bv->bv_page); | 917 | src_p = kmap_atomic(src_bv->bv_page); |
| 918 | dst_p = kmap_atomic(dst_bv->bv_page); | 918 | dst_p = kmap_atomic(dst_bv->bv_page); |
| 919 | 919 | ||
| 920 | memcpy(dst_p + dst_bv->bv_offset, | 920 | memcpy(dst_p + dst_offset, |
| 921 | src_p + src_bv->bv_offset, | 921 | src_p + src_offset, |
| 922 | bytes); | 922 | bytes); |
| 923 | 923 | ||
| 924 | kunmap_atomic(dst_p); | 924 | kunmap_atomic(dst_p); |
diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c index 58b7d14b08ee..08cc08f037a6 100644 --- a/fs/btrfs/async-thread.c +++ b/fs/btrfs/async-thread.c | |||
| @@ -107,7 +107,8 @@ static void check_idle_worker(struct btrfs_worker_thread *worker) | |||
| 107 | worker->idle = 1; | 107 | worker->idle = 1; |
| 108 | 108 | ||
| 109 | /* the list may be empty if the worker is just starting */ | 109 | /* the list may be empty if the worker is just starting */ |
| 110 | if (!list_empty(&worker->worker_list)) { | 110 | if (!list_empty(&worker->worker_list) && |
| 111 | !worker->workers->stopping) { | ||
| 111 | list_move(&worker->worker_list, | 112 | list_move(&worker->worker_list, |
| 112 | &worker->workers->idle_list); | 113 | &worker->workers->idle_list); |
| 113 | } | 114 | } |
| @@ -127,7 +128,8 @@ static void check_busy_worker(struct btrfs_worker_thread *worker) | |||
| 127 | spin_lock_irqsave(&worker->workers->lock, flags); | 128 | spin_lock_irqsave(&worker->workers->lock, flags); |
| 128 | worker->idle = 0; | 129 | worker->idle = 0; |
| 129 | 130 | ||
| 130 | if (!list_empty(&worker->worker_list)) { | 131 | if (!list_empty(&worker->worker_list) && |
| 132 | !worker->workers->stopping) { | ||
| 131 | list_move_tail(&worker->worker_list, | 133 | list_move_tail(&worker->worker_list, |
| 132 | &worker->workers->worker_list); | 134 | &worker->workers->worker_list); |
| 133 | } | 135 | } |
| @@ -412,6 +414,7 @@ void btrfs_stop_workers(struct btrfs_workers *workers) | |||
| 412 | int can_stop; | 414 | int can_stop; |
| 413 | 415 | ||
| 414 | spin_lock_irq(&workers->lock); | 416 | spin_lock_irq(&workers->lock); |
| 417 | workers->stopping = 1; | ||
| 415 | list_splice_init(&workers->idle_list, &workers->worker_list); | 418 | list_splice_init(&workers->idle_list, &workers->worker_list); |
| 416 | while (!list_empty(&workers->worker_list)) { | 419 | while (!list_empty(&workers->worker_list)) { |
| 417 | cur = workers->worker_list.next; | 420 | cur = workers->worker_list.next; |
| @@ -455,6 +458,7 @@ void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max, | |||
| 455 | workers->ordered = 0; | 458 | workers->ordered = 0; |
| 456 | workers->atomic_start_pending = 0; | 459 | workers->atomic_start_pending = 0; |
| 457 | workers->atomic_worker_start = async_helper; | 460 | workers->atomic_worker_start = async_helper; |
| 461 | workers->stopping = 0; | ||
| 458 | } | 462 | } |
| 459 | 463 | ||
| 460 | /* | 464 | /* |
| @@ -480,15 +484,19 @@ static int __btrfs_start_workers(struct btrfs_workers *workers) | |||
| 480 | atomic_set(&worker->num_pending, 0); | 484 | atomic_set(&worker->num_pending, 0); |
| 481 | atomic_set(&worker->refs, 1); | 485 | atomic_set(&worker->refs, 1); |
| 482 | worker->workers = workers; | 486 | worker->workers = workers; |
| 483 | worker->task = kthread_run(worker_loop, worker, | 487 | worker->task = kthread_create(worker_loop, worker, |
| 484 | "btrfs-%s-%d", workers->name, | 488 | "btrfs-%s-%d", workers->name, |
| 485 | workers->num_workers + 1); | 489 | workers->num_workers + 1); |
| 486 | if (IS_ERR(worker->task)) { | 490 | if (IS_ERR(worker->task)) { |
| 487 | ret = PTR_ERR(worker->task); | 491 | ret = PTR_ERR(worker->task); |
| 488 | kfree(worker); | ||
| 489 | goto fail; | 492 | goto fail; |
| 490 | } | 493 | } |
| 494 | |||
| 491 | spin_lock_irq(&workers->lock); | 495 | spin_lock_irq(&workers->lock); |
| 496 | if (workers->stopping) { | ||
| 497 | spin_unlock_irq(&workers->lock); | ||
| 498 | goto fail_kthread; | ||
| 499 | } | ||
| 492 | list_add_tail(&worker->worker_list, &workers->idle_list); | 500 | list_add_tail(&worker->worker_list, &workers->idle_list); |
| 493 | worker->idle = 1; | 501 | worker->idle = 1; |
| 494 | workers->num_workers++; | 502 | workers->num_workers++; |
| @@ -496,8 +504,13 @@ static int __btrfs_start_workers(struct btrfs_workers *workers) | |||
| 496 | WARN_ON(workers->num_workers_starting < 0); | 504 | WARN_ON(workers->num_workers_starting < 0); |
| 497 | spin_unlock_irq(&workers->lock); | 505 | spin_unlock_irq(&workers->lock); |
| 498 | 506 | ||
| 507 | wake_up_process(worker->task); | ||
| 499 | return 0; | 508 | return 0; |
| 509 | |||
| 510 | fail_kthread: | ||
| 511 | kthread_stop(worker->task); | ||
| 500 | fail: | 512 | fail: |
| 513 | kfree(worker); | ||
| 501 | spin_lock_irq(&workers->lock); | 514 | spin_lock_irq(&workers->lock); |
| 502 | workers->num_workers_starting--; | 515 | workers->num_workers_starting--; |
| 503 | spin_unlock_irq(&workers->lock); | 516 | spin_unlock_irq(&workers->lock); |
diff --git a/fs/btrfs/async-thread.h b/fs/btrfs/async-thread.h index 063698b90ce2..1f26792683ed 100644 --- a/fs/btrfs/async-thread.h +++ b/fs/btrfs/async-thread.h | |||
| @@ -107,6 +107,8 @@ struct btrfs_workers { | |||
| 107 | 107 | ||
| 108 | /* extra name for this worker, used for current->name */ | 108 | /* extra name for this worker, used for current->name */ |
| 109 | char *name; | 109 | char *name; |
| 110 | |||
| 111 | int stopping; | ||
| 110 | }; | 112 | }; |
| 111 | 113 | ||
| 112 | void btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work); | 114 | void btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work); |
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index 70681686e8dc..9efb94e95858 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c | |||
| @@ -535,10 +535,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, | |||
| 535 | list_add(&tgt_device->dev_alloc_list, &fs_info->fs_devices->alloc_list); | 535 | list_add(&tgt_device->dev_alloc_list, &fs_info->fs_devices->alloc_list); |
| 536 | 536 | ||
| 537 | btrfs_rm_dev_replace_srcdev(fs_info, src_device); | 537 | btrfs_rm_dev_replace_srcdev(fs_info, src_device); |
| 538 | if (src_device->bdev) { | 538 | |
| 539 | /* zero out the old super */ | ||
| 540 | btrfs_scratch_superblock(src_device); | ||
| 541 | } | ||
| 542 | /* | 539 | /* |
| 543 | * this is again a consistent state where no dev_replace procedure | 540 | * this is again a consistent state where no dev_replace procedure |
| 544 | * is running, the target device is part of the filesystem, the | 541 | * is running, the target device is part of the filesystem, the |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index c09a40db53db..22bda32acb89 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
| @@ -145,8 +145,16 @@ int __init extent_io_init(void) | |||
| 145 | offsetof(struct btrfs_io_bio, bio)); | 145 | offsetof(struct btrfs_io_bio, bio)); |
| 146 | if (!btrfs_bioset) | 146 | if (!btrfs_bioset) |
| 147 | goto free_buffer_cache; | 147 | goto free_buffer_cache; |
| 148 | |||
| 149 | if (bioset_integrity_create(btrfs_bioset, BIO_POOL_SIZE)) | ||
| 150 | goto free_bioset; | ||
| 151 | |||
| 148 | return 0; | 152 | return 0; |
| 149 | 153 | ||
| 154 | free_bioset: | ||
| 155 | bioset_free(btrfs_bioset); | ||
| 156 | btrfs_bioset = NULL; | ||
| 157 | |||
| 150 | free_buffer_cache: | 158 | free_buffer_cache: |
| 151 | kmem_cache_destroy(extent_buffer_cache); | 159 | kmem_cache_destroy(extent_buffer_cache); |
| 152 | extent_buffer_cache = NULL; | 160 | extent_buffer_cache = NULL; |
| @@ -1614,7 +1622,7 @@ again: | |||
| 1614 | *start = delalloc_start; | 1622 | *start = delalloc_start; |
| 1615 | *end = delalloc_end; | 1623 | *end = delalloc_end; |
| 1616 | free_extent_state(cached_state); | 1624 | free_extent_state(cached_state); |
| 1617 | return found; | 1625 | return 0; |
| 1618 | } | 1626 | } |
| 1619 | 1627 | ||
| 1620 | /* | 1628 | /* |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index e7a95356df83..8c81bdc1ef9b 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -1838,11 +1838,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 1838 | assert_qgroups_uptodate(trans); | 1838 | assert_qgroups_uptodate(trans); |
| 1839 | update_super_roots(root); | 1839 | update_super_roots(root); |
| 1840 | 1840 | ||
| 1841 | if (!root->fs_info->log_root_recovering) { | 1841 | btrfs_set_super_log_root(root->fs_info->super_copy, 0); |
| 1842 | btrfs_set_super_log_root(root->fs_info->super_copy, 0); | 1842 | btrfs_set_super_log_root_level(root->fs_info->super_copy, 0); |
| 1843 | btrfs_set_super_log_root_level(root->fs_info->super_copy, 0); | ||
| 1844 | } | ||
| 1845 | |||
| 1846 | memcpy(root->fs_info->super_for_commit, root->fs_info->super_copy, | 1843 | memcpy(root->fs_info->super_for_commit, root->fs_info->super_copy, |
| 1847 | sizeof(*root->fs_info->super_copy)); | 1844 | sizeof(*root->fs_info->super_copy)); |
| 1848 | 1845 | ||
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index a10645830223..043b215769c2 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
| @@ -1716,6 +1716,7 @@ void btrfs_rm_dev_replace_srcdev(struct btrfs_fs_info *fs_info, | |||
| 1716 | struct btrfs_device *srcdev) | 1716 | struct btrfs_device *srcdev) |
| 1717 | { | 1717 | { |
| 1718 | WARN_ON(!mutex_is_locked(&fs_info->fs_devices->device_list_mutex)); | 1718 | WARN_ON(!mutex_is_locked(&fs_info->fs_devices->device_list_mutex)); |
| 1719 | |||
| 1719 | list_del_rcu(&srcdev->dev_list); | 1720 | list_del_rcu(&srcdev->dev_list); |
| 1720 | list_del_rcu(&srcdev->dev_alloc_list); | 1721 | list_del_rcu(&srcdev->dev_alloc_list); |
| 1721 | fs_info->fs_devices->num_devices--; | 1722 | fs_info->fs_devices->num_devices--; |
| @@ -1725,9 +1726,13 @@ void btrfs_rm_dev_replace_srcdev(struct btrfs_fs_info *fs_info, | |||
| 1725 | } | 1726 | } |
| 1726 | if (srcdev->can_discard) | 1727 | if (srcdev->can_discard) |
| 1727 | fs_info->fs_devices->num_can_discard--; | 1728 | fs_info->fs_devices->num_can_discard--; |
| 1728 | if (srcdev->bdev) | 1729 | if (srcdev->bdev) { |
| 1729 | fs_info->fs_devices->open_devices--; | 1730 | fs_info->fs_devices->open_devices--; |
| 1730 | 1731 | ||
| 1732 | /* zero out the old super */ | ||
| 1733 | btrfs_scratch_superblock(srcdev); | ||
| 1734 | } | ||
| 1735 | |||
| 1731 | call_rcu(&srcdev->rcu, free_device); | 1736 | call_rcu(&srcdev->rcu, free_device); |
| 1732 | } | 1737 | } |
| 1733 | 1738 | ||
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index ea723a5e8226..6d0b07217ac9 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
| @@ -132,5 +132,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | |||
| 132 | extern const struct export_operations cifs_export_ops; | 132 | extern const struct export_operations cifs_export_ops; |
| 133 | #endif /* CONFIG_CIFS_NFSD_EXPORT */ | 133 | #endif /* CONFIG_CIFS_NFSD_EXPORT */ |
| 134 | 134 | ||
| 135 | #define CIFS_VERSION "2.01" | 135 | #define CIFS_VERSION "2.02" |
| 136 | #endif /* _CIFSFS_H */ | 136 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index cfa14c80ef3b..52b6f6c26bfc 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -547,9 +547,6 @@ struct TCP_Server_Info { | |||
| 547 | unsigned int max_rw; /* maxRw specifies the maximum */ | 547 | unsigned int max_rw; /* maxRw specifies the maximum */ |
| 548 | /* message size the server can send or receive for */ | 548 | /* message size the server can send or receive for */ |
| 549 | /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */ | 549 | /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */ |
| 550 | unsigned int max_vcs; /* maximum number of smb sessions, at least | ||
| 551 | those that can be specified uniquely with | ||
| 552 | vcnumbers */ | ||
| 553 | unsigned int capabilities; /* selective disabling of caps by smb sess */ | 550 | unsigned int capabilities; /* selective disabling of caps by smb sess */ |
| 554 | int timeAdj; /* Adjust for difference in server time zone in sec */ | 551 | int timeAdj; /* Adjust for difference in server time zone in sec */ |
| 555 | __u64 CurrentMid; /* multiplex id - rotating counter */ | 552 | __u64 CurrentMid; /* multiplex id - rotating counter */ |
| @@ -715,7 +712,6 @@ struct cifs_ses { | |||
| 715 | enum statusEnum status; | 712 | enum statusEnum status; |
| 716 | unsigned overrideSecFlg; /* if non-zero override global sec flags */ | 713 | unsigned overrideSecFlg; /* if non-zero override global sec flags */ |
| 717 | __u16 ipc_tid; /* special tid for connection to IPC share */ | 714 | __u16 ipc_tid; /* special tid for connection to IPC share */ |
| 718 | __u16 vcnum; | ||
| 719 | char *serverOS; /* name of operating system underlying server */ | 715 | char *serverOS; /* name of operating system underlying server */ |
| 720 | char *serverNOS; /* name of network operating system of server */ | 716 | char *serverNOS; /* name of network operating system of server */ |
| 721 | char *serverDomain; /* security realm of server */ | 717 | char *serverDomain; /* security realm of server */ |
| @@ -1272,6 +1268,7 @@ struct dfs_info3_param { | |||
| 1272 | #define CIFS_FATTR_DELETE_PENDING 0x2 | 1268 | #define CIFS_FATTR_DELETE_PENDING 0x2 |
| 1273 | #define CIFS_FATTR_NEED_REVAL 0x4 | 1269 | #define CIFS_FATTR_NEED_REVAL 0x4 |
| 1274 | #define CIFS_FATTR_INO_COLLISION 0x8 | 1270 | #define CIFS_FATTR_INO_COLLISION 0x8 |
| 1271 | #define CIFS_FATTR_UNKNOWN_NLINK 0x10 | ||
| 1275 | 1272 | ||
| 1276 | struct cifs_fattr { | 1273 | struct cifs_fattr { |
| 1277 | u32 cf_flags; | 1274 | u32 cf_flags; |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 948676db8e2e..a630475e421c 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
| @@ -2652,26 +2652,7 @@ typedef struct file_xattr_info { | |||
| 2652 | } __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute info | 2652 | } __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute info |
| 2653 | level 0x205 */ | 2653 | level 0x205 */ |
| 2654 | 2654 | ||
| 2655 | 2655 | /* flags for lsattr and chflags commands removed arein uapi/linux/fs.h */ | |
| 2656 | /* flags for chattr command */ | ||
| 2657 | #define EXT_SECURE_DELETE 0x00000001 /* EXT3_SECRM_FL */ | ||
| 2658 | #define EXT_ENABLE_UNDELETE 0x00000002 /* EXT3_UNRM_FL */ | ||
| 2659 | /* Reserved for compress file 0x4 */ | ||
| 2660 | #define EXT_SYNCHRONOUS 0x00000008 /* EXT3_SYNC_FL */ | ||
| 2661 | #define EXT_IMMUTABLE_FL 0x00000010 /* EXT3_IMMUTABLE_FL */ | ||
| 2662 | #define EXT_OPEN_APPEND_ONLY 0x00000020 /* EXT3_APPEND_FL */ | ||
| 2663 | #define EXT_DO_NOT_BACKUP 0x00000040 /* EXT3_NODUMP_FL */ | ||
| 2664 | #define EXT_NO_UPDATE_ATIME 0x00000080 /* EXT3_NOATIME_FL */ | ||
| 2665 | /* 0x100 through 0x800 reserved for compression flags and are GET-ONLY */ | ||
| 2666 | #define EXT_HASH_TREE_INDEXED_DIR 0x00001000 /* GET-ONLY EXT3_INDEX_FL */ | ||
| 2667 | /* 0x2000 reserved for IMAGIC_FL */ | ||
| 2668 | #define EXT_JOURNAL_THIS_FILE 0x00004000 /* GET-ONLY EXT3_JOURNAL_DATA_FL */ | ||
| 2669 | /* 0x8000 reserved for EXT3_NOTAIL_FL */ | ||
| 2670 | #define EXT_SYNCHRONOUS_DIR 0x00010000 /* EXT3_DIRSYNC_FL */ | ||
| 2671 | #define EXT_TOPDIR 0x00020000 /* EXT3_TOPDIR_FL */ | ||
| 2672 | |||
| 2673 | #define EXT_SET_MASK 0x000300FF | ||
| 2674 | #define EXT_GET_MASK 0x0003DFFF | ||
| 2675 | 2656 | ||
| 2676 | typedef struct file_chattr_info { | 2657 | typedef struct file_chattr_info { |
| 2677 | __le64 mask; /* list of all possible attribute bits */ | 2658 | __le64 mask; /* list of all possible attribute bits */ |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index a3d74fea1623..4baf35949b51 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -463,7 +463,6 @@ decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr) | |||
| 463 | cifs_max_pending); | 463 | cifs_max_pending); |
| 464 | set_credits(server, server->maxReq); | 464 | set_credits(server, server->maxReq); |
| 465 | server->maxBuf = le16_to_cpu(rsp->MaxBufSize); | 465 | server->maxBuf = le16_to_cpu(rsp->MaxBufSize); |
| 466 | server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); | ||
| 467 | /* even though we do not use raw we might as well set this | 466 | /* even though we do not use raw we might as well set this |
| 468 | accurately, in case we ever find a need for it */ | 467 | accurately, in case we ever find a need for it */ |
| 469 | if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { | 468 | if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index eb955b525e55..7ddddf2e2504 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -3254,6 +3254,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
| 3254 | /* | 3254 | /* |
| 3255 | * Reads as many pages as possible from fscache. Returns -ENOBUFS | 3255 | * Reads as many pages as possible from fscache. Returns -ENOBUFS |
| 3256 | * immediately if the cookie is negative | 3256 | * immediately if the cookie is negative |
| 3257 | * | ||
| 3258 | * After this point, every page in the list might have PG_fscache set, | ||
| 3259 | * so we will need to clean that up off of every page we don't use. | ||
| 3257 | */ | 3260 | */ |
| 3258 | rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list, | 3261 | rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list, |
| 3259 | &num_pages); | 3262 | &num_pages); |
| @@ -3376,6 +3379,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
| 3376 | kref_put(&rdata->refcount, cifs_readdata_release); | 3379 | kref_put(&rdata->refcount, cifs_readdata_release); |
| 3377 | } | 3380 | } |
| 3378 | 3381 | ||
| 3382 | /* Any pages that have been shown to fscache but didn't get added to | ||
| 3383 | * the pagecache must be uncached before they get returned to the | ||
| 3384 | * allocator. | ||
| 3385 | */ | ||
| 3386 | cifs_fscache_readpages_cancel(mapping->host, page_list); | ||
| 3379 | return rc; | 3387 | return rc; |
| 3380 | } | 3388 | } |
| 3381 | 3389 | ||
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c index 2f4bc5a58054..b3258f35e88a 100644 --- a/fs/cifs/fscache.c +++ b/fs/cifs/fscache.c | |||
| @@ -223,6 +223,13 @@ void __cifs_readpage_to_fscache(struct inode *inode, struct page *page) | |||
| 223 | fscache_uncache_page(CIFS_I(inode)->fscache, page); | 223 | fscache_uncache_page(CIFS_I(inode)->fscache, page); |
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | void __cifs_fscache_readpages_cancel(struct inode *inode, struct list_head *pages) | ||
| 227 | { | ||
| 228 | cifs_dbg(FYI, "%s: (fsc: %p, i: %p)\n", | ||
| 229 | __func__, CIFS_I(inode)->fscache, inode); | ||
| 230 | fscache_readpages_cancel(CIFS_I(inode)->fscache, pages); | ||
| 231 | } | ||
| 232 | |||
| 226 | void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode) | 233 | void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode) |
| 227 | { | 234 | { |
| 228 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | 235 | struct cifsInodeInfo *cifsi = CIFS_I(inode); |
diff --git a/fs/cifs/fscache.h b/fs/cifs/fscache.h index 63539323e0b9..24794b6cd8ec 100644 --- a/fs/cifs/fscache.h +++ b/fs/cifs/fscache.h | |||
| @@ -54,6 +54,7 @@ extern int __cifs_readpages_from_fscache(struct inode *, | |||
| 54 | struct address_space *, | 54 | struct address_space *, |
| 55 | struct list_head *, | 55 | struct list_head *, |
| 56 | unsigned *); | 56 | unsigned *); |
| 57 | extern void __cifs_fscache_readpages_cancel(struct inode *, struct list_head *); | ||
| 57 | 58 | ||
| 58 | extern void __cifs_readpage_to_fscache(struct inode *, struct page *); | 59 | extern void __cifs_readpage_to_fscache(struct inode *, struct page *); |
| 59 | 60 | ||
| @@ -91,6 +92,13 @@ static inline void cifs_readpage_to_fscache(struct inode *inode, | |||
| 91 | __cifs_readpage_to_fscache(inode, page); | 92 | __cifs_readpage_to_fscache(inode, page); |
| 92 | } | 93 | } |
| 93 | 94 | ||
| 95 | static inline void cifs_fscache_readpages_cancel(struct inode *inode, | ||
| 96 | struct list_head *pages) | ||
| 97 | { | ||
| 98 | if (CIFS_I(inode)->fscache) | ||
| 99 | return __cifs_fscache_readpages_cancel(inode, pages); | ||
| 100 | } | ||
| 101 | |||
| 94 | #else /* CONFIG_CIFS_FSCACHE */ | 102 | #else /* CONFIG_CIFS_FSCACHE */ |
| 95 | static inline int cifs_fscache_register(void) { return 0; } | 103 | static inline int cifs_fscache_register(void) { return 0; } |
| 96 | static inline void cifs_fscache_unregister(void) {} | 104 | static inline void cifs_fscache_unregister(void) {} |
| @@ -131,6 +139,11 @@ static inline int cifs_readpages_from_fscache(struct inode *inode, | |||
| 131 | static inline void cifs_readpage_to_fscache(struct inode *inode, | 139 | static inline void cifs_readpage_to_fscache(struct inode *inode, |
| 132 | struct page *page) {} | 140 | struct page *page) {} |
| 133 | 141 | ||
| 142 | static inline void cifs_fscache_readpages_cancel(struct inode *inode, | ||
| 143 | struct list_head *pages) | ||
| 144 | { | ||
| 145 | } | ||
| 146 | |||
| 134 | #endif /* CONFIG_CIFS_FSCACHE */ | 147 | #endif /* CONFIG_CIFS_FSCACHE */ |
| 135 | 148 | ||
| 136 | #endif /* _CIFS_FSCACHE_H */ | 149 | #endif /* _CIFS_FSCACHE_H */ |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index f9ff9c173f78..867b7cdc794a 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -120,6 +120,33 @@ cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr) | |||
| 120 | cifs_i->invalid_mapping = true; | 120 | cifs_i->invalid_mapping = true; |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | /* | ||
| 124 | * copy nlink to the inode, unless it wasn't provided. Provide | ||
| 125 | * sane values if we don't have an existing one and none was provided | ||
| 126 | */ | ||
| 127 | static void | ||
| 128 | cifs_nlink_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) | ||
| 129 | { | ||
| 130 | /* | ||
| 131 | * if we're in a situation where we can't trust what we | ||
| 132 | * got from the server (readdir, some non-unix cases) | ||
| 133 | * fake reasonable values | ||
| 134 | */ | ||
| 135 | if (fattr->cf_flags & CIFS_FATTR_UNKNOWN_NLINK) { | ||
| 136 | /* only provide fake values on a new inode */ | ||
| 137 | if (inode->i_state & I_NEW) { | ||
| 138 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) | ||
| 139 | set_nlink(inode, 2); | ||
| 140 | else | ||
| 141 | set_nlink(inode, 1); | ||
| 142 | } | ||
| 143 | return; | ||
| 144 | } | ||
| 145 | |||
| 146 | /* we trust the server, so update it */ | ||
| 147 | set_nlink(inode, fattr->cf_nlink); | ||
| 148 | } | ||
| 149 | |||
| 123 | /* populate an inode with info from a cifs_fattr struct */ | 150 | /* populate an inode with info from a cifs_fattr struct */ |
| 124 | void | 151 | void |
| 125 | cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) | 152 | cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) |
| @@ -134,7 +161,7 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) | |||
| 134 | inode->i_mtime = fattr->cf_mtime; | 161 | inode->i_mtime = fattr->cf_mtime; |
| 135 | inode->i_ctime = fattr->cf_ctime; | 162 | inode->i_ctime = fattr->cf_ctime; |
| 136 | inode->i_rdev = fattr->cf_rdev; | 163 | inode->i_rdev = fattr->cf_rdev; |
| 137 | set_nlink(inode, fattr->cf_nlink); | 164 | cifs_nlink_fattr_to_inode(inode, fattr); |
| 138 | inode->i_uid = fattr->cf_uid; | 165 | inode->i_uid = fattr->cf_uid; |
| 139 | inode->i_gid = fattr->cf_gid; | 166 | inode->i_gid = fattr->cf_gid; |
| 140 | 167 | ||
| @@ -541,6 +568,7 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, | |||
| 541 | fattr->cf_bytes = le64_to_cpu(info->AllocationSize); | 568 | fattr->cf_bytes = le64_to_cpu(info->AllocationSize); |
| 542 | fattr->cf_createtime = le64_to_cpu(info->CreationTime); | 569 | fattr->cf_createtime = le64_to_cpu(info->CreationTime); |
| 543 | 570 | ||
| 571 | fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); | ||
| 544 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { | 572 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { |
| 545 | fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; | 573 | fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; |
| 546 | fattr->cf_dtype = DT_DIR; | 574 | fattr->cf_dtype = DT_DIR; |
| @@ -548,7 +576,8 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, | |||
| 548 | * Server can return wrong NumberOfLinks value for directories | 576 | * Server can return wrong NumberOfLinks value for directories |
| 549 | * when Unix extensions are disabled - fake it. | 577 | * when Unix extensions are disabled - fake it. |
| 550 | */ | 578 | */ |
| 551 | fattr->cf_nlink = 2; | 579 | if (!tcon->unix_ext) |
| 580 | fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK; | ||
| 552 | } else if (fattr->cf_cifsattrs & ATTR_REPARSE) { | 581 | } else if (fattr->cf_cifsattrs & ATTR_REPARSE) { |
| 553 | fattr->cf_mode = S_IFLNK; | 582 | fattr->cf_mode = S_IFLNK; |
| 554 | fattr->cf_dtype = DT_LNK; | 583 | fattr->cf_dtype = DT_LNK; |
| @@ -561,11 +590,15 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, | |||
| 561 | if (fattr->cf_cifsattrs & ATTR_READONLY) | 590 | if (fattr->cf_cifsattrs & ATTR_READONLY) |
| 562 | fattr->cf_mode &= ~(S_IWUGO); | 591 | fattr->cf_mode &= ~(S_IWUGO); |
| 563 | 592 | ||
| 564 | fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); | 593 | /* |
| 565 | if (fattr->cf_nlink < 1) { | 594 | * Don't accept zero nlink from non-unix servers unless |
| 566 | cifs_dbg(1, "replacing bogus file nlink value %u\n", | 595 | * delete is pending. Instead mark it as unknown. |
| 596 | */ | ||
| 597 | if ((fattr->cf_nlink < 1) && !tcon->unix_ext && | ||
| 598 | !info->DeletePending) { | ||
| 599 | cifs_dbg(1, "bogus file nlink value %u\n", | ||
| 567 | fattr->cf_nlink); | 600 | fattr->cf_nlink); |
| 568 | fattr->cf_nlink = 1; | 601 | fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK; |
| 569 | } | 602 | } |
| 570 | } | 603 | } |
| 571 | 604 | ||
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 42ef03be089f..53a75f3d0179 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
| @@ -180,6 +180,9 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) | |||
| 180 | fattr->cf_dtype = DT_REG; | 180 | fattr->cf_dtype = DT_REG; |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | /* non-unix readdir doesn't provide nlink */ | ||
| 184 | fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK; | ||
| 185 | |||
| 183 | if (fattr->cf_cifsattrs & ATTR_READONLY) | 186 | if (fattr->cf_cifsattrs & ATTR_READONLY) |
| 184 | fattr->cf_mode &= ~S_IWUGO; | 187 | fattr->cf_mode &= ~S_IWUGO; |
| 185 | 188 | ||
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 5f99b7f19e78..352358de1d7e 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
| @@ -32,88 +32,6 @@ | |||
| 32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
| 33 | #include "cifs_spnego.h" | 33 | #include "cifs_spnego.h" |
| 34 | 34 | ||
| 35 | /* | ||
| 36 | * Checks if this is the first smb session to be reconnected after | ||
| 37 | * the socket has been reestablished (so we know whether to use vc 0). | ||
| 38 | * Called while holding the cifs_tcp_ses_lock, so do not block | ||
| 39 | */ | ||
| 40 | static bool is_first_ses_reconnect(struct cifs_ses *ses) | ||
| 41 | { | ||
| 42 | struct list_head *tmp; | ||
| 43 | struct cifs_ses *tmp_ses; | ||
| 44 | |||
| 45 | list_for_each(tmp, &ses->server->smb_ses_list) { | ||
| 46 | tmp_ses = list_entry(tmp, struct cifs_ses, | ||
| 47 | smb_ses_list); | ||
| 48 | if (tmp_ses->need_reconnect == false) | ||
| 49 | return false; | ||
| 50 | } | ||
| 51 | /* could not find a session that was already connected, | ||
| 52 | this must be the first one we are reconnecting */ | ||
| 53 | return true; | ||
| 54 | } | ||
| 55 | |||
| 56 | /* | ||
| 57 | * vc number 0 is treated specially by some servers, and should be the | ||
| 58 | * first one we request. After that we can use vcnumbers up to maxvcs, | ||
| 59 | * one for each smb session (some Windows versions set maxvcs incorrectly | ||
| 60 | * so maxvc=1 can be ignored). If we have too many vcs, we can reuse | ||
| 61 | * any vc but zero (some servers reset the connection on vcnum zero) | ||
| 62 | * | ||
| 63 | */ | ||
| 64 | static __le16 get_next_vcnum(struct cifs_ses *ses) | ||
| 65 | { | ||
| 66 | __u16 vcnum = 0; | ||
| 67 | struct list_head *tmp; | ||
| 68 | struct cifs_ses *tmp_ses; | ||
| 69 | __u16 max_vcs = ses->server->max_vcs; | ||
| 70 | __u16 i; | ||
| 71 | int free_vc_found = 0; | ||
| 72 | |||
| 73 | /* Quoting the MS-SMB specification: "Windows-based SMB servers set this | ||
| 74 | field to one but do not enforce this limit, which allows an SMB client | ||
| 75 | to establish more virtual circuits than allowed by this value ... but | ||
| 76 | other server implementations can enforce this limit." */ | ||
| 77 | if (max_vcs < 2) | ||
| 78 | max_vcs = 0xFFFF; | ||
| 79 | |||
| 80 | spin_lock(&cifs_tcp_ses_lock); | ||
| 81 | if ((ses->need_reconnect) && is_first_ses_reconnect(ses)) | ||
| 82 | goto get_vc_num_exit; /* vcnum will be zero */ | ||
| 83 | for (i = ses->server->srv_count - 1; i < max_vcs; i++) { | ||
| 84 | if (i == 0) /* this is the only connection, use vc 0 */ | ||
| 85 | break; | ||
| 86 | |||
| 87 | free_vc_found = 1; | ||
| 88 | |||
| 89 | list_for_each(tmp, &ses->server->smb_ses_list) { | ||
| 90 | tmp_ses = list_entry(tmp, struct cifs_ses, | ||
| 91 | smb_ses_list); | ||
| 92 | if (tmp_ses->vcnum == i) { | ||
| 93 | free_vc_found = 0; | ||
| 94 | break; /* found duplicate, try next vcnum */ | ||
| 95 | } | ||
| 96 | } | ||
| 97 | if (free_vc_found) | ||
| 98 | break; /* we found a vcnumber that will work - use it */ | ||
| 99 | } | ||
| 100 | |||
| 101 | if (i == 0) | ||
| 102 | vcnum = 0; /* for most common case, ie if one smb session, use | ||
| 103 | vc zero. Also for case when no free vcnum, zero | ||
| 104 | is safest to send (some clients only send zero) */ | ||
| 105 | else if (free_vc_found == 0) | ||
| 106 | vcnum = 1; /* we can not reuse vc=0 safely, since some servers | ||
| 107 | reset all uids on that, but 1 is ok. */ | ||
| 108 | else | ||
| 109 | vcnum = i; | ||
| 110 | ses->vcnum = vcnum; | ||
| 111 | get_vc_num_exit: | ||
| 112 | spin_unlock(&cifs_tcp_ses_lock); | ||
| 113 | |||
| 114 | return cpu_to_le16(vcnum); | ||
| 115 | } | ||
| 116 | |||
| 117 | static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, SESSION_SETUP_ANDX *pSMB) | 35 | static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, SESSION_SETUP_ANDX *pSMB) |
| 118 | { | 36 | { |
| 119 | __u32 capabilities = 0; | 37 | __u32 capabilities = 0; |
| @@ -128,7 +46,7 @@ static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, SESSION_SETUP_ANDX *pSMB) | |||
| 128 | CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4, | 46 | CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4, |
| 129 | USHRT_MAX)); | 47 | USHRT_MAX)); |
| 130 | pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); | 48 | pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); |
| 131 | pSMB->req.VcNumber = get_next_vcnum(ses); | 49 | pSMB->req.VcNumber = __constant_cpu_to_le16(1); |
| 132 | 50 | ||
| 133 | /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */ | 51 | /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */ |
| 134 | 52 | ||
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 62b43b577bfc..b7989f2ab4c4 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
| @@ -182,6 +182,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) | |||
| 182 | struct inode *inode; | 182 | struct inode *inode; |
| 183 | struct dentry *parent; | 183 | struct dentry *parent; |
| 184 | struct fuse_conn *fc; | 184 | struct fuse_conn *fc; |
| 185 | struct fuse_inode *fi; | ||
| 185 | int ret; | 186 | int ret; |
| 186 | 187 | ||
| 187 | inode = ACCESS_ONCE(entry->d_inode); | 188 | inode = ACCESS_ONCE(entry->d_inode); |
| @@ -228,7 +229,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) | |||
| 228 | if (!err && !outarg.nodeid) | 229 | if (!err && !outarg.nodeid) |
| 229 | err = -ENOENT; | 230 | err = -ENOENT; |
| 230 | if (!err) { | 231 | if (!err) { |
| 231 | struct fuse_inode *fi = get_fuse_inode(inode); | 232 | fi = get_fuse_inode(inode); |
| 232 | if (outarg.nodeid != get_node_id(inode)) { | 233 | if (outarg.nodeid != get_node_id(inode)) { |
| 233 | fuse_queue_forget(fc, forget, outarg.nodeid, 1); | 234 | fuse_queue_forget(fc, forget, outarg.nodeid, 1); |
| 234 | goto invalid; | 235 | goto invalid; |
| @@ -246,8 +247,11 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) | |||
| 246 | attr_version); | 247 | attr_version); |
| 247 | fuse_change_entry_timeout(entry, &outarg); | 248 | fuse_change_entry_timeout(entry, &outarg); |
| 248 | } else if (inode) { | 249 | } else if (inode) { |
| 249 | fc = get_fuse_conn(inode); | 250 | fi = get_fuse_inode(inode); |
| 250 | if (fc->readdirplus_auto) { | 251 | if (flags & LOOKUP_RCU) { |
| 252 | if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state)) | ||
| 253 | return -ECHILD; | ||
| 254 | } else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) { | ||
| 251 | parent = dget_parent(entry); | 255 | parent = dget_parent(entry); |
| 252 | fuse_advise_use_readdirplus(parent->d_inode); | 256 | fuse_advise_use_readdirplus(parent->d_inode); |
| 253 | dput(parent); | 257 | dput(parent); |
| @@ -259,7 +263,8 @@ out: | |||
| 259 | 263 | ||
| 260 | invalid: | 264 | invalid: |
| 261 | ret = 0; | 265 | ret = 0; |
| 262 | if (check_submounts_and_drop(entry) != 0) | 266 | |
| 267 | if (!(flags & LOOKUP_RCU) && check_submounts_and_drop(entry) != 0) | ||
| 263 | ret = 1; | 268 | ret = 1; |
| 264 | goto out; | 269 | goto out; |
| 265 | } | 270 | } |
| @@ -1063,6 +1068,8 @@ static int fuse_access(struct inode *inode, int mask) | |||
| 1063 | struct fuse_access_in inarg; | 1068 | struct fuse_access_in inarg; |
| 1064 | int err; | 1069 | int err; |
| 1065 | 1070 | ||
| 1071 | BUG_ON(mask & MAY_NOT_BLOCK); | ||
| 1072 | |||
| 1066 | if (fc->no_access) | 1073 | if (fc->no_access) |
| 1067 | return 0; | 1074 | return 0; |
| 1068 | 1075 | ||
| @@ -1150,9 +1157,6 @@ static int fuse_permission(struct inode *inode, int mask) | |||
| 1150 | noticed immediately, only after the attribute | 1157 | noticed immediately, only after the attribute |
| 1151 | timeout has expired */ | 1158 | timeout has expired */ |
| 1152 | } else if (mask & (MAY_ACCESS | MAY_CHDIR)) { | 1159 | } else if (mask & (MAY_ACCESS | MAY_CHDIR)) { |
| 1153 | if (mask & MAY_NOT_BLOCK) | ||
| 1154 | return -ECHILD; | ||
| 1155 | |||
| 1156 | err = fuse_access(inode, mask); | 1160 | err = fuse_access(inode, mask); |
| 1157 | } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { | 1161 | } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { |
| 1158 | if (!(inode->i_mode & S_IXUGO)) { | 1162 | if (!(inode->i_mode & S_IXUGO)) { |
| @@ -1291,6 +1295,8 @@ static int fuse_direntplus_link(struct file *file, | |||
| 1291 | } | 1295 | } |
| 1292 | 1296 | ||
| 1293 | found: | 1297 | found: |
| 1298 | if (fc->readdirplus_auto) | ||
| 1299 | set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state); | ||
| 1294 | fuse_change_entry_timeout(dentry, o); | 1300 | fuse_change_entry_timeout(dentry, o); |
| 1295 | 1301 | ||
| 1296 | err = 0; | 1302 | err = 0; |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index d409deafc67b..4598345ab87d 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
| @@ -2467,6 +2467,7 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, | |||
| 2467 | { | 2467 | { |
| 2468 | struct fuse_file *ff = file->private_data; | 2468 | struct fuse_file *ff = file->private_data; |
| 2469 | struct inode *inode = file->f_inode; | 2469 | struct inode *inode = file->f_inode; |
| 2470 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
| 2470 | struct fuse_conn *fc = ff->fc; | 2471 | struct fuse_conn *fc = ff->fc; |
| 2471 | struct fuse_req *req; | 2472 | struct fuse_req *req; |
| 2472 | struct fuse_fallocate_in inarg = { | 2473 | struct fuse_fallocate_in inarg = { |
| @@ -2484,10 +2485,20 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, | |||
| 2484 | 2485 | ||
| 2485 | if (lock_inode) { | 2486 | if (lock_inode) { |
| 2486 | mutex_lock(&inode->i_mutex); | 2487 | mutex_lock(&inode->i_mutex); |
| 2487 | if (mode & FALLOC_FL_PUNCH_HOLE) | 2488 | if (mode & FALLOC_FL_PUNCH_HOLE) { |
| 2488 | fuse_set_nowrite(inode); | 2489 | loff_t endbyte = offset + length - 1; |
| 2490 | err = filemap_write_and_wait_range(inode->i_mapping, | ||
| 2491 | offset, endbyte); | ||
| 2492 | if (err) | ||
| 2493 | goto out; | ||
| 2494 | |||
| 2495 | fuse_sync_writes(inode); | ||
| 2496 | } | ||
| 2489 | } | 2497 | } |
| 2490 | 2498 | ||
| 2499 | if (!(mode & FALLOC_FL_KEEP_SIZE)) | ||
| 2500 | set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); | ||
| 2501 | |||
| 2491 | req = fuse_get_req_nopages(fc); | 2502 | req = fuse_get_req_nopages(fc); |
| 2492 | if (IS_ERR(req)) { | 2503 | if (IS_ERR(req)) { |
| 2493 | err = PTR_ERR(req); | 2504 | err = PTR_ERR(req); |
| @@ -2520,11 +2531,11 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, | |||
| 2520 | fuse_invalidate_attr(inode); | 2531 | fuse_invalidate_attr(inode); |
| 2521 | 2532 | ||
| 2522 | out: | 2533 | out: |
| 2523 | if (lock_inode) { | 2534 | if (!(mode & FALLOC_FL_KEEP_SIZE)) |
| 2524 | if (mode & FALLOC_FL_PUNCH_HOLE) | 2535 | clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); |
| 2525 | fuse_release_nowrite(inode); | 2536 | |
| 2537 | if (lock_inode) | ||
| 2526 | mutex_unlock(&inode->i_mutex); | 2538 | mutex_unlock(&inode->i_mutex); |
| 2527 | } | ||
| 2528 | 2539 | ||
| 2529 | return err; | 2540 | return err; |
| 2530 | } | 2541 | } |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 5ced199b50bb..5b9e6f3b6aef 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
| @@ -115,6 +115,8 @@ struct fuse_inode { | |||
| 115 | enum { | 115 | enum { |
| 116 | /** Advise readdirplus */ | 116 | /** Advise readdirplus */ |
| 117 | FUSE_I_ADVISE_RDPLUS, | 117 | FUSE_I_ADVISE_RDPLUS, |
| 118 | /** Initialized with readdirplus */ | ||
| 119 | FUSE_I_INIT_RDPLUS, | ||
| 118 | /** An operation changing file size is in progress */ | 120 | /** An operation changing file size is in progress */ |
| 119 | FUSE_I_SIZE_UNSTABLE, | 121 | FUSE_I_SIZE_UNSTABLE, |
| 120 | }; | 122 | }; |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 854a8f05a610..02b0df769e2d 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -1458,7 +1458,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
| 1458 | 1458 | ||
| 1459 | trace_nfs_atomic_open_enter(dir, ctx, open_flags); | 1459 | trace_nfs_atomic_open_enter(dir, ctx, open_flags); |
| 1460 | nfs_block_sillyrename(dentry->d_parent); | 1460 | nfs_block_sillyrename(dentry->d_parent); |
| 1461 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr); | 1461 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr, opened); |
| 1462 | nfs_unblock_sillyrename(dentry->d_parent); | 1462 | nfs_unblock_sillyrename(dentry->d_parent); |
| 1463 | if (IS_ERR(inode)) { | 1463 | if (IS_ERR(inode)) { |
| 1464 | err = PTR_ERR(inode); | 1464 | err = PTR_ERR(inode); |
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index e5b804dd944c..77efaf15ec90 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c | |||
| @@ -19,6 +19,7 @@ nfs4_file_open(struct inode *inode, struct file *filp) | |||
| 19 | struct inode *dir; | 19 | struct inode *dir; |
| 20 | unsigned openflags = filp->f_flags; | 20 | unsigned openflags = filp->f_flags; |
| 21 | struct iattr attr; | 21 | struct iattr attr; |
| 22 | int opened = 0; | ||
| 22 | int err; | 23 | int err; |
| 23 | 24 | ||
| 24 | /* | 25 | /* |
| @@ -55,7 +56,7 @@ nfs4_file_open(struct inode *inode, struct file *filp) | |||
| 55 | nfs_wb_all(inode); | 56 | nfs_wb_all(inode); |
| 56 | } | 57 | } |
| 57 | 58 | ||
| 58 | inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr); | 59 | inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr, &opened); |
| 59 | if (IS_ERR(inode)) { | 60 | if (IS_ERR(inode)) { |
| 60 | err = PTR_ERR(inode); | 61 | err = PTR_ERR(inode); |
| 61 | switch (err) { | 62 | switch (err) { |
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c index 95604f64cab8..c7c295e556ed 100644 --- a/fs/nfs/nfs4filelayoutdev.c +++ b/fs/nfs/nfs4filelayoutdev.c | |||
| @@ -185,6 +185,7 @@ nfs4_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds) | |||
| 185 | if (status) | 185 | if (status) |
| 186 | goto out_put; | 186 | goto out_put; |
| 187 | 187 | ||
| 188 | smp_wmb(); | ||
| 188 | ds->ds_clp = clp; | 189 | ds->ds_clp = clp; |
| 189 | dprintk("%s [new] addr: %s\n", __func__, ds->ds_remotestr); | 190 | dprintk("%s [new] addr: %s\n", __func__, ds->ds_remotestr); |
| 190 | out: | 191 | out: |
| @@ -801,34 +802,35 @@ nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx) | |||
| 801 | struct nfs4_file_layout_dsaddr *dsaddr = FILELAYOUT_LSEG(lseg)->dsaddr; | 802 | struct nfs4_file_layout_dsaddr *dsaddr = FILELAYOUT_LSEG(lseg)->dsaddr; |
| 802 | struct nfs4_pnfs_ds *ds = dsaddr->ds_list[ds_idx]; | 803 | struct nfs4_pnfs_ds *ds = dsaddr->ds_list[ds_idx]; |
| 803 | struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg); | 804 | struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg); |
| 804 | 805 | struct nfs4_pnfs_ds *ret = ds; | |
| 805 | if (filelayout_test_devid_unavailable(devid)) | ||
| 806 | return NULL; | ||
| 807 | 806 | ||
| 808 | if (ds == NULL) { | 807 | if (ds == NULL) { |
| 809 | printk(KERN_ERR "NFS: %s: No data server for offset index %d\n", | 808 | printk(KERN_ERR "NFS: %s: No data server for offset index %d\n", |
| 810 | __func__, ds_idx); | 809 | __func__, ds_idx); |
| 811 | filelayout_mark_devid_invalid(devid); | 810 | filelayout_mark_devid_invalid(devid); |
| 812 | return NULL; | 811 | goto out; |
| 813 | } | 812 | } |
| 813 | smp_rmb(); | ||
| 814 | if (ds->ds_clp) | 814 | if (ds->ds_clp) |
| 815 | return ds; | 815 | goto out_test_devid; |
| 816 | 816 | ||
| 817 | if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) { | 817 | if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) { |
| 818 | struct nfs_server *s = NFS_SERVER(lseg->pls_layout->plh_inode); | 818 | struct nfs_server *s = NFS_SERVER(lseg->pls_layout->plh_inode); |
| 819 | int err; | 819 | int err; |
| 820 | 820 | ||
| 821 | err = nfs4_ds_connect(s, ds); | 821 | err = nfs4_ds_connect(s, ds); |
| 822 | if (err) { | 822 | if (err) |
| 823 | nfs4_mark_deviceid_unavailable(devid); | 823 | nfs4_mark_deviceid_unavailable(devid); |
| 824 | ds = NULL; | ||
| 825 | } | ||
| 826 | nfs4_clear_ds_conn_bit(ds); | 824 | nfs4_clear_ds_conn_bit(ds); |
| 827 | } else { | 825 | } else { |
| 828 | /* Either ds is connected, or ds is NULL */ | 826 | /* Either ds is connected, or ds is NULL */ |
| 829 | nfs4_wait_ds_connect(ds); | 827 | nfs4_wait_ds_connect(ds); |
| 830 | } | 828 | } |
| 831 | return ds; | 829 | out_test_devid: |
| 830 | if (filelayout_test_devid_unavailable(devid)) | ||
| 831 | ret = NULL; | ||
| 832 | out: | ||
| 833 | return ret; | ||
| 832 | } | 834 | } |
| 833 | 835 | ||
| 834 | module_param(dataserver_retrans, uint, 0644); | 836 | module_param(dataserver_retrans, uint, 0644); |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 989bb9d3074d..d53d6785cba2 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -912,6 +912,7 @@ struct nfs4_opendata { | |||
| 912 | struct iattr attrs; | 912 | struct iattr attrs; |
| 913 | unsigned long timestamp; | 913 | unsigned long timestamp; |
| 914 | unsigned int rpc_done : 1; | 914 | unsigned int rpc_done : 1; |
| 915 | unsigned int file_created : 1; | ||
| 915 | unsigned int is_recover : 1; | 916 | unsigned int is_recover : 1; |
| 916 | int rpc_status; | 917 | int rpc_status; |
| 917 | int cancelled; | 918 | int cancelled; |
| @@ -1946,8 +1947,13 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) | |||
| 1946 | 1947 | ||
| 1947 | nfs_fattr_map_and_free_names(server, &data->f_attr); | 1948 | nfs_fattr_map_and_free_names(server, &data->f_attr); |
| 1948 | 1949 | ||
| 1949 | if (o_arg->open_flags & O_CREAT) | 1950 | if (o_arg->open_flags & O_CREAT) { |
| 1950 | update_changeattr(dir, &o_res->cinfo); | 1951 | update_changeattr(dir, &o_res->cinfo); |
| 1952 | if (o_arg->open_flags & O_EXCL) | ||
| 1953 | data->file_created = 1; | ||
| 1954 | else if (o_res->cinfo.before != o_res->cinfo.after) | ||
| 1955 | data->file_created = 1; | ||
| 1956 | } | ||
| 1951 | if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0) | 1957 | if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0) |
| 1952 | server->caps &= ~NFS_CAP_POSIX_LOCK; | 1958 | server->caps &= ~NFS_CAP_POSIX_LOCK; |
| 1953 | if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { | 1959 | if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { |
| @@ -2191,7 +2197,8 @@ static int _nfs4_do_open(struct inode *dir, | |||
| 2191 | struct nfs_open_context *ctx, | 2197 | struct nfs_open_context *ctx, |
| 2192 | int flags, | 2198 | int flags, |
| 2193 | struct iattr *sattr, | 2199 | struct iattr *sattr, |
| 2194 | struct nfs4_label *label) | 2200 | struct nfs4_label *label, |
| 2201 | int *opened) | ||
| 2195 | { | 2202 | { |
| 2196 | struct nfs4_state_owner *sp; | 2203 | struct nfs4_state_owner *sp; |
| 2197 | struct nfs4_state *state = NULL; | 2204 | struct nfs4_state *state = NULL; |
| @@ -2261,6 +2268,8 @@ static int _nfs4_do_open(struct inode *dir, | |||
| 2261 | nfs_setsecurity(state->inode, opendata->o_res.f_attr, olabel); | 2268 | nfs_setsecurity(state->inode, opendata->o_res.f_attr, olabel); |
| 2262 | } | 2269 | } |
| 2263 | } | 2270 | } |
| 2271 | if (opendata->file_created) | ||
| 2272 | *opened |= FILE_CREATED; | ||
| 2264 | 2273 | ||
| 2265 | if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server)) | 2274 | if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server)) |
| 2266 | *ctx_th = opendata->f_attr.mdsthreshold; | 2275 | *ctx_th = opendata->f_attr.mdsthreshold; |
| @@ -2289,7 +2298,8 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, | |||
| 2289 | struct nfs_open_context *ctx, | 2298 | struct nfs_open_context *ctx, |
| 2290 | int flags, | 2299 | int flags, |
| 2291 | struct iattr *sattr, | 2300 | struct iattr *sattr, |
| 2292 | struct nfs4_label *label) | 2301 | struct nfs4_label *label, |
| 2302 | int *opened) | ||
| 2293 | { | 2303 | { |
| 2294 | struct nfs_server *server = NFS_SERVER(dir); | 2304 | struct nfs_server *server = NFS_SERVER(dir); |
| 2295 | struct nfs4_exception exception = { }; | 2305 | struct nfs4_exception exception = { }; |
| @@ -2297,7 +2307,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, | |||
| 2297 | int status; | 2307 | int status; |
| 2298 | 2308 | ||
| 2299 | do { | 2309 | do { |
| 2300 | status = _nfs4_do_open(dir, ctx, flags, sattr, label); | 2310 | status = _nfs4_do_open(dir, ctx, flags, sattr, label, opened); |
| 2301 | res = ctx->state; | 2311 | res = ctx->state; |
| 2302 | trace_nfs4_open_file(ctx, flags, status); | 2312 | trace_nfs4_open_file(ctx, flags, status); |
| 2303 | if (status == 0) | 2313 | if (status == 0) |
| @@ -2659,7 +2669,8 @@ out: | |||
| 2659 | } | 2669 | } |
| 2660 | 2670 | ||
| 2661 | static struct inode * | 2671 | static struct inode * |
| 2662 | nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr) | 2672 | nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, |
| 2673 | int open_flags, struct iattr *attr, int *opened) | ||
| 2663 | { | 2674 | { |
| 2664 | struct nfs4_state *state; | 2675 | struct nfs4_state *state; |
| 2665 | struct nfs4_label l = {0, 0, 0, NULL}, *label = NULL; | 2676 | struct nfs4_label l = {0, 0, 0, NULL}, *label = NULL; |
| @@ -2667,7 +2678,7 @@ nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags | |||
| 2667 | label = nfs4_label_init_security(dir, ctx->dentry, attr, &l); | 2678 | label = nfs4_label_init_security(dir, ctx->dentry, attr, &l); |
| 2668 | 2679 | ||
| 2669 | /* Protect against concurrent sillydeletes */ | 2680 | /* Protect against concurrent sillydeletes */ |
| 2670 | state = nfs4_do_open(dir, ctx, open_flags, attr, label); | 2681 | state = nfs4_do_open(dir, ctx, open_flags, attr, label, opened); |
| 2671 | 2682 | ||
| 2672 | nfs4_label_release_security(label); | 2683 | nfs4_label_release_security(label); |
| 2673 | 2684 | ||
| @@ -3332,6 +3343,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
| 3332 | struct nfs4_label l, *ilabel = NULL; | 3343 | struct nfs4_label l, *ilabel = NULL; |
| 3333 | struct nfs_open_context *ctx; | 3344 | struct nfs_open_context *ctx; |
| 3334 | struct nfs4_state *state; | 3345 | struct nfs4_state *state; |
| 3346 | int opened = 0; | ||
| 3335 | int status = 0; | 3347 | int status = 0; |
| 3336 | 3348 | ||
| 3337 | ctx = alloc_nfs_open_context(dentry, FMODE_READ); | 3349 | ctx = alloc_nfs_open_context(dentry, FMODE_READ); |
| @@ -3341,7 +3353,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
| 3341 | ilabel = nfs4_label_init_security(dir, dentry, sattr, &l); | 3353 | ilabel = nfs4_label_init_security(dir, dentry, sattr, &l); |
| 3342 | 3354 | ||
| 3343 | sattr->ia_mode &= ~current_umask(); | 3355 | sattr->ia_mode &= ~current_umask(); |
| 3344 | state = nfs4_do_open(dir, ctx, flags, sattr, ilabel); | 3356 | state = nfs4_do_open(dir, ctx, flags, sattr, ilabel, &opened); |
| 3345 | if (IS_ERR(state)) { | 3357 | if (IS_ERR(state)) { |
| 3346 | status = PTR_ERR(state); | 3358 | status = PTR_ERR(state); |
| 3347 | goto out; | 3359 | goto out; |
| @@ -7564,8 +7576,10 @@ nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 7564 | { | 7576 | { |
| 7565 | int err; | 7577 | int err; |
| 7566 | struct page *page; | 7578 | struct page *page; |
| 7567 | rpc_authflavor_t flavor; | 7579 | rpc_authflavor_t flavor = RPC_AUTH_MAXFLAVOR; |
| 7568 | struct nfs4_secinfo_flavors *flavors; | 7580 | struct nfs4_secinfo_flavors *flavors; |
| 7581 | struct nfs4_secinfo4 *secinfo; | ||
| 7582 | int i; | ||
| 7569 | 7583 | ||
| 7570 | page = alloc_page(GFP_KERNEL); | 7584 | page = alloc_page(GFP_KERNEL); |
| 7571 | if (!page) { | 7585 | if (!page) { |
| @@ -7587,9 +7601,31 @@ nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 7587 | if (err) | 7601 | if (err) |
| 7588 | goto out_freepage; | 7602 | goto out_freepage; |
| 7589 | 7603 | ||
| 7590 | flavor = nfs_find_best_sec(flavors); | 7604 | for (i = 0; i < flavors->num_flavors; i++) { |
| 7591 | if (err == 0) | 7605 | secinfo = &flavors->flavors[i]; |
| 7592 | err = nfs4_lookup_root_sec(server, fhandle, info, flavor); | 7606 | |
| 7607 | switch (secinfo->flavor) { | ||
| 7608 | case RPC_AUTH_NULL: | ||
| 7609 | case RPC_AUTH_UNIX: | ||
| 7610 | case RPC_AUTH_GSS: | ||
| 7611 | flavor = rpcauth_get_pseudoflavor(secinfo->flavor, | ||
| 7612 | &secinfo->flavor_info); | ||
| 7613 | break; | ||
| 7614 | default: | ||
| 7615 | flavor = RPC_AUTH_MAXFLAVOR; | ||
| 7616 | break; | ||
| 7617 | } | ||
| 7618 | |||
| 7619 | if (flavor != RPC_AUTH_MAXFLAVOR) { | ||
| 7620 | err = nfs4_lookup_root_sec(server, fhandle, | ||
| 7621 | info, flavor); | ||
| 7622 | if (!err) | ||
| 7623 | break; | ||
| 7624 | } | ||
| 7625 | } | ||
| 7626 | |||
| 7627 | if (flavor == RPC_AUTH_MAXFLAVOR) | ||
| 7628 | err = -EPERM; | ||
| 7593 | 7629 | ||
| 7594 | out_freepage: | 7630 | out_freepage: |
| 7595 | put_page(page); | 7631 | put_page(page); |
diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c index 0ba679866e50..da276640f776 100644 --- a/fs/nilfs2/page.c +++ b/fs/nilfs2/page.c | |||
| @@ -94,6 +94,7 @@ void nilfs_forget_buffer(struct buffer_head *bh) | |||
| 94 | clear_buffer_nilfs_volatile(bh); | 94 | clear_buffer_nilfs_volatile(bh); |
| 95 | clear_buffer_nilfs_checked(bh); | 95 | clear_buffer_nilfs_checked(bh); |
| 96 | clear_buffer_nilfs_redirected(bh); | 96 | clear_buffer_nilfs_redirected(bh); |
| 97 | clear_buffer_async_write(bh); | ||
| 97 | clear_buffer_dirty(bh); | 98 | clear_buffer_dirty(bh); |
| 98 | if (nilfs_page_buffers_clean(page)) | 99 | if (nilfs_page_buffers_clean(page)) |
| 99 | __nilfs_clear_page_dirty(page); | 100 | __nilfs_clear_page_dirty(page); |
| @@ -429,6 +430,7 @@ void nilfs_clear_dirty_page(struct page *page, bool silent) | |||
| 429 | "discard block %llu, size %zu", | 430 | "discard block %llu, size %zu", |
| 430 | (u64)bh->b_blocknr, bh->b_size); | 431 | (u64)bh->b_blocknr, bh->b_size); |
| 431 | } | 432 | } |
| 433 | clear_buffer_async_write(bh); | ||
| 432 | clear_buffer_dirty(bh); | 434 | clear_buffer_dirty(bh); |
| 433 | clear_buffer_nilfs_volatile(bh); | 435 | clear_buffer_nilfs_volatile(bh); |
| 434 | clear_buffer_nilfs_checked(bh); | 436 | clear_buffer_nilfs_checked(bh); |
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index bd88a7461063..9f6b486b6c01 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
| @@ -665,7 +665,7 @@ static size_t nilfs_lookup_dirty_data_buffers(struct inode *inode, | |||
| 665 | 665 | ||
| 666 | bh = head = page_buffers(page); | 666 | bh = head = page_buffers(page); |
| 667 | do { | 667 | do { |
| 668 | if (!buffer_dirty(bh)) | 668 | if (!buffer_dirty(bh) || buffer_async_write(bh)) |
| 669 | continue; | 669 | continue; |
| 670 | get_bh(bh); | 670 | get_bh(bh); |
| 671 | list_add_tail(&bh->b_assoc_buffers, listp); | 671 | list_add_tail(&bh->b_assoc_buffers, listp); |
| @@ -699,7 +699,8 @@ static void nilfs_lookup_dirty_node_buffers(struct inode *inode, | |||
| 699 | for (i = 0; i < pagevec_count(&pvec); i++) { | 699 | for (i = 0; i < pagevec_count(&pvec); i++) { |
| 700 | bh = head = page_buffers(pvec.pages[i]); | 700 | bh = head = page_buffers(pvec.pages[i]); |
| 701 | do { | 701 | do { |
| 702 | if (buffer_dirty(bh)) { | 702 | if (buffer_dirty(bh) && |
| 703 | !buffer_async_write(bh)) { | ||
| 703 | get_bh(bh); | 704 | get_bh(bh); |
| 704 | list_add_tail(&bh->b_assoc_buffers, | 705 | list_add_tail(&bh->b_assoc_buffers, |
| 705 | listp); | 706 | listp); |
| @@ -1579,6 +1580,7 @@ static void nilfs_segctor_prepare_write(struct nilfs_sc_info *sci) | |||
| 1579 | 1580 | ||
| 1580 | list_for_each_entry(bh, &segbuf->sb_segsum_buffers, | 1581 | list_for_each_entry(bh, &segbuf->sb_segsum_buffers, |
| 1581 | b_assoc_buffers) { | 1582 | b_assoc_buffers) { |
| 1583 | set_buffer_async_write(bh); | ||
| 1582 | if (bh->b_page != bd_page) { | 1584 | if (bh->b_page != bd_page) { |
| 1583 | if (bd_page) { | 1585 | if (bd_page) { |
| 1584 | lock_page(bd_page); | 1586 | lock_page(bd_page); |
| @@ -1592,6 +1594,7 @@ static void nilfs_segctor_prepare_write(struct nilfs_sc_info *sci) | |||
| 1592 | 1594 | ||
| 1593 | list_for_each_entry(bh, &segbuf->sb_payload_buffers, | 1595 | list_for_each_entry(bh, &segbuf->sb_payload_buffers, |
| 1594 | b_assoc_buffers) { | 1596 | b_assoc_buffers) { |
| 1597 | set_buffer_async_write(bh); | ||
| 1595 | if (bh == segbuf->sb_super_root) { | 1598 | if (bh == segbuf->sb_super_root) { |
| 1596 | if (bh->b_page != bd_page) { | 1599 | if (bh->b_page != bd_page) { |
| 1597 | lock_page(bd_page); | 1600 | lock_page(bd_page); |
| @@ -1677,6 +1680,7 @@ static void nilfs_abort_logs(struct list_head *logs, int err) | |||
| 1677 | list_for_each_entry(segbuf, logs, sb_list) { | 1680 | list_for_each_entry(segbuf, logs, sb_list) { |
| 1678 | list_for_each_entry(bh, &segbuf->sb_segsum_buffers, | 1681 | list_for_each_entry(bh, &segbuf->sb_segsum_buffers, |
| 1679 | b_assoc_buffers) { | 1682 | b_assoc_buffers) { |
| 1683 | clear_buffer_async_write(bh); | ||
| 1680 | if (bh->b_page != bd_page) { | 1684 | if (bh->b_page != bd_page) { |
| 1681 | if (bd_page) | 1685 | if (bd_page) |
| 1682 | end_page_writeback(bd_page); | 1686 | end_page_writeback(bd_page); |
| @@ -1686,6 +1690,7 @@ static void nilfs_abort_logs(struct list_head *logs, int err) | |||
| 1686 | 1690 | ||
| 1687 | list_for_each_entry(bh, &segbuf->sb_payload_buffers, | 1691 | list_for_each_entry(bh, &segbuf->sb_payload_buffers, |
| 1688 | b_assoc_buffers) { | 1692 | b_assoc_buffers) { |
| 1693 | clear_buffer_async_write(bh); | ||
| 1689 | if (bh == segbuf->sb_super_root) { | 1694 | if (bh == segbuf->sb_super_root) { |
| 1690 | if (bh->b_page != bd_page) { | 1695 | if (bh->b_page != bd_page) { |
| 1691 | end_page_writeback(bd_page); | 1696 | end_page_writeback(bd_page); |
| @@ -1755,6 +1760,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) | |||
| 1755 | b_assoc_buffers) { | 1760 | b_assoc_buffers) { |
| 1756 | set_buffer_uptodate(bh); | 1761 | set_buffer_uptodate(bh); |
| 1757 | clear_buffer_dirty(bh); | 1762 | clear_buffer_dirty(bh); |
| 1763 | clear_buffer_async_write(bh); | ||
| 1758 | if (bh->b_page != bd_page) { | 1764 | if (bh->b_page != bd_page) { |
| 1759 | if (bd_page) | 1765 | if (bd_page) |
| 1760 | end_page_writeback(bd_page); | 1766 | end_page_writeback(bd_page); |
| @@ -1776,6 +1782,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) | |||
| 1776 | b_assoc_buffers) { | 1782 | b_assoc_buffers) { |
| 1777 | set_buffer_uptodate(bh); | 1783 | set_buffer_uptodate(bh); |
| 1778 | clear_buffer_dirty(bh); | 1784 | clear_buffer_dirty(bh); |
| 1785 | clear_buffer_async_write(bh); | ||
| 1779 | clear_buffer_delay(bh); | 1786 | clear_buffer_delay(bh); |
| 1780 | clear_buffer_nilfs_volatile(bh); | 1787 | clear_buffer_nilfs_volatile(bh); |
| 1781 | clear_buffer_nilfs_redirected(bh); | 1788 | clear_buffer_nilfs_redirected(bh); |
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index ef999729e274..0d3a97d2d5f6 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c | |||
| @@ -70,9 +70,10 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, unsigned int flags) | |||
| 70 | */ | 70 | */ |
| 71 | if (inode == NULL) { | 71 | if (inode == NULL) { |
| 72 | unsigned long gen = (unsigned long) dentry->d_fsdata; | 72 | unsigned long gen = (unsigned long) dentry->d_fsdata; |
| 73 | unsigned long pgen = | 73 | unsigned long pgen; |
| 74 | OCFS2_I(dentry->d_parent->d_inode)->ip_dir_lock_gen; | 74 | spin_lock(&dentry->d_lock); |
| 75 | 75 | pgen = OCFS2_I(dentry->d_parent->d_inode)->ip_dir_lock_gen; | |
| 76 | spin_unlock(&dentry->d_lock); | ||
| 76 | trace_ocfs2_dentry_revalidate_negative(dentry->d_name.len, | 77 | trace_ocfs2_dentry_revalidate_negative(dentry->d_name.len, |
| 77 | dentry->d_name.name, | 78 | dentry->d_name.name, |
| 78 | pgen, gen); | 79 | pgen, gen); |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 121da2dc3be8..d4e81e4a9b04 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
| @@ -1924,7 +1924,7 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) | |||
| 1924 | { | 1924 | { |
| 1925 | int tmp, hangup_needed = 0; | 1925 | int tmp, hangup_needed = 0; |
| 1926 | struct ocfs2_super *osb = NULL; | 1926 | struct ocfs2_super *osb = NULL; |
| 1927 | char nodestr[8]; | 1927 | char nodestr[12]; |
| 1928 | 1928 | ||
| 1929 | trace_ocfs2_dismount_volume(sb); | 1929 | trace_ocfs2_dismount_volume(sb); |
| 1930 | 1930 | ||
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 73feacc49b2e..fd777032c2ba 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c | |||
| @@ -1163,21 +1163,6 @@ static struct reiserfs_journal_list *find_newer_jl_for_cn(struct | |||
| 1163 | return NULL; | 1163 | return NULL; |
| 1164 | } | 1164 | } |
| 1165 | 1165 | ||
| 1166 | static int newer_jl_done(struct reiserfs_journal_cnode *cn) | ||
| 1167 | { | ||
| 1168 | struct super_block *sb = cn->sb; | ||
| 1169 | b_blocknr_t blocknr = cn->blocknr; | ||
| 1170 | |||
| 1171 | cn = cn->hprev; | ||
| 1172 | while (cn) { | ||
| 1173 | if (cn->sb == sb && cn->blocknr == blocknr && cn->jlist && | ||
| 1174 | atomic_read(&cn->jlist->j_commit_left) != 0) | ||
| 1175 | return 0; | ||
| 1176 | cn = cn->hprev; | ||
| 1177 | } | ||
| 1178 | return 1; | ||
| 1179 | } | ||
| 1180 | |||
| 1181 | static void remove_journal_hash(struct super_block *, | 1166 | static void remove_journal_hash(struct super_block *, |
| 1182 | struct reiserfs_journal_cnode **, | 1167 | struct reiserfs_journal_cnode **, |
| 1183 | struct reiserfs_journal_list *, unsigned long, | 1168 | struct reiserfs_journal_list *, unsigned long, |
| @@ -1353,7 +1338,6 @@ static int flush_journal_list(struct super_block *s, | |||
| 1353 | reiserfs_warning(s, "clm-2048", "called with wcount %d", | 1338 | reiserfs_warning(s, "clm-2048", "called with wcount %d", |
| 1354 | atomic_read(&journal->j_wcount)); | 1339 | atomic_read(&journal->j_wcount)); |
| 1355 | } | 1340 | } |
| 1356 | BUG_ON(jl->j_trans_id == 0); | ||
| 1357 | 1341 | ||
| 1358 | /* if flushall == 0, the lock is already held */ | 1342 | /* if flushall == 0, the lock is already held */ |
| 1359 | if (flushall) { | 1343 | if (flushall) { |
| @@ -1593,31 +1577,6 @@ static int flush_journal_list(struct super_block *s, | |||
| 1593 | return err; | 1577 | return err; |
| 1594 | } | 1578 | } |
| 1595 | 1579 | ||
| 1596 | static int test_transaction(struct super_block *s, | ||
| 1597 | struct reiserfs_journal_list *jl) | ||
| 1598 | { | ||
| 1599 | struct reiserfs_journal_cnode *cn; | ||
| 1600 | |||
| 1601 | if (jl->j_len == 0 || atomic_read(&jl->j_nonzerolen) == 0) | ||
| 1602 | return 1; | ||
| 1603 | |||
| 1604 | cn = jl->j_realblock; | ||
| 1605 | while (cn) { | ||
| 1606 | /* if the blocknr == 0, this has been cleared from the hash, | ||
| 1607 | ** skip it | ||
| 1608 | */ | ||
| 1609 | if (cn->blocknr == 0) { | ||
| 1610 | goto next; | ||
| 1611 | } | ||
| 1612 | if (cn->bh && !newer_jl_done(cn)) | ||
| 1613 | return 0; | ||
| 1614 | next: | ||
| 1615 | cn = cn->next; | ||
| 1616 | cond_resched(); | ||
| 1617 | } | ||
| 1618 | return 0; | ||
| 1619 | } | ||
| 1620 | |||
| 1621 | static int write_one_transaction(struct super_block *s, | 1580 | static int write_one_transaction(struct super_block *s, |
| 1622 | struct reiserfs_journal_list *jl, | 1581 | struct reiserfs_journal_list *jl, |
| 1623 | struct buffer_chunk *chunk) | 1582 | struct buffer_chunk *chunk) |
| @@ -1805,6 +1764,8 @@ static int flush_used_journal_lists(struct super_block *s, | |||
| 1805 | break; | 1764 | break; |
| 1806 | tjl = JOURNAL_LIST_ENTRY(tjl->j_list.next); | 1765 | tjl = JOURNAL_LIST_ENTRY(tjl->j_list.next); |
| 1807 | } | 1766 | } |
| 1767 | get_journal_list(jl); | ||
| 1768 | get_journal_list(flush_jl); | ||
| 1808 | /* try to find a group of blocks we can flush across all the | 1769 | /* try to find a group of blocks we can flush across all the |
| 1809 | ** transactions, but only bother if we've actually spanned | 1770 | ** transactions, but only bother if we've actually spanned |
| 1810 | ** across multiple lists | 1771 | ** across multiple lists |
| @@ -1813,6 +1774,8 @@ static int flush_used_journal_lists(struct super_block *s, | |||
| 1813 | ret = kupdate_transactions(s, jl, &tjl, &trans_id, len, i); | 1774 | ret = kupdate_transactions(s, jl, &tjl, &trans_id, len, i); |
| 1814 | } | 1775 | } |
| 1815 | flush_journal_list(s, flush_jl, 1); | 1776 | flush_journal_list(s, flush_jl, 1); |
| 1777 | put_journal_list(s, flush_jl); | ||
| 1778 | put_journal_list(s, jl); | ||
| 1816 | return 0; | 1779 | return 0; |
| 1817 | } | 1780 | } |
| 1818 | 1781 | ||
| @@ -3868,27 +3831,6 @@ int reiserfs_prepare_for_journal(struct super_block *sb, | |||
| 3868 | return 1; | 3831 | return 1; |
| 3869 | } | 3832 | } |
| 3870 | 3833 | ||
| 3871 | static void flush_old_journal_lists(struct super_block *s) | ||
| 3872 | { | ||
| 3873 | struct reiserfs_journal *journal = SB_JOURNAL(s); | ||
| 3874 | struct reiserfs_journal_list *jl; | ||
| 3875 | struct list_head *entry; | ||
| 3876 | time_t now = get_seconds(); | ||
| 3877 | |||
| 3878 | while (!list_empty(&journal->j_journal_list)) { | ||
| 3879 | entry = journal->j_journal_list.next; | ||
| 3880 | jl = JOURNAL_LIST_ENTRY(entry); | ||
| 3881 | /* this check should always be run, to send old lists to disk */ | ||
| 3882 | if (jl->j_timestamp < (now - (JOURNAL_MAX_TRANS_AGE * 4)) && | ||
| 3883 | atomic_read(&jl->j_commit_left) == 0 && | ||
| 3884 | test_transaction(s, jl)) { | ||
| 3885 | flush_used_journal_lists(s, jl); | ||
| 3886 | } else { | ||
| 3887 | break; | ||
| 3888 | } | ||
| 3889 | } | ||
| 3890 | } | ||
| 3891 | |||
| 3892 | /* | 3834 | /* |
| 3893 | ** long and ugly. If flush, will not return until all commit | 3835 | ** long and ugly. If flush, will not return until all commit |
| 3894 | ** blocks and all real buffers in the trans are on disk. | 3836 | ** blocks and all real buffers in the trans are on disk. |
| @@ -4232,7 +4174,6 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, | |||
| 4232 | } | 4174 | } |
| 4233 | } | 4175 | } |
| 4234 | } | 4176 | } |
| 4235 | flush_old_journal_lists(sb); | ||
| 4236 | 4177 | ||
| 4237 | journal->j_current_jl->j_list_bitmap = | 4178 | journal->j_current_jl->j_list_bitmap = |
| 4238 | get_list_bitmap(sb, journal->j_current_jl); | 4179 | get_list_bitmap(sb, journal->j_current_jl); |
diff --git a/fs/super.c b/fs/super.c index 3a96c9783a8b..0225c20f8770 100644 --- a/fs/super.c +++ b/fs/super.c | |||
| @@ -264,6 +264,8 @@ out_free_sb: | |||
| 264 | */ | 264 | */ |
| 265 | static inline void destroy_super(struct super_block *s) | 265 | static inline void destroy_super(struct super_block *s) |
| 266 | { | 266 | { |
| 267 | list_lru_destroy(&s->s_dentry_lru); | ||
| 268 | list_lru_destroy(&s->s_inode_lru); | ||
| 267 | #ifdef CONFIG_SMP | 269 | #ifdef CONFIG_SMP |
| 268 | free_percpu(s->s_files); | 270 | free_percpu(s->s_files); |
| 269 | #endif | 271 | #endif |
| @@ -323,8 +325,6 @@ void deactivate_locked_super(struct super_block *s) | |||
| 323 | 325 | ||
| 324 | /* caches are now gone, we can safely kill the shrinker now */ | 326 | /* caches are now gone, we can safely kill the shrinker now */ |
| 325 | unregister_shrinker(&s->s_shrink); | 327 | unregister_shrinker(&s->s_shrink); |
| 326 | list_lru_destroy(&s->s_dentry_lru); | ||
| 327 | list_lru_destroy(&s->s_inode_lru); | ||
| 328 | 328 | ||
| 329 | put_filesystem(fs); | 329 | put_filesystem(fs); |
| 330 | put_super(s); | 330 | put_super(s); |
diff --git a/fs/sysv/super.c b/fs/sysv/super.c index d0c6a007ce83..eda10959714f 100644 --- a/fs/sysv/super.c +++ b/fs/sysv/super.c | |||
| @@ -487,6 +487,7 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent) | |||
| 487 | sbi->s_sb = sb; | 487 | sbi->s_sb = sb; |
| 488 | sbi->s_block_base = 0; | 488 | sbi->s_block_base = 0; |
| 489 | sbi->s_type = FSTYPE_V7; | 489 | sbi->s_type = FSTYPE_V7; |
| 490 | mutex_init(&sbi->s_lock); | ||
| 490 | sb->s_fs_info = sbi; | 491 | sb->s_fs_info = sbi; |
| 491 | 492 | ||
| 492 | sb_set_blocksize(sb, 512); | 493 | sb_set_blocksize(sb, 512); |
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c index 7e5aae4bf46f..6eaf5edf1ea1 100644 --- a/fs/udf/ialloc.c +++ b/fs/udf/ialloc.c | |||
| @@ -30,18 +30,17 @@ void udf_free_inode(struct inode *inode) | |||
| 30 | { | 30 | { |
| 31 | struct super_block *sb = inode->i_sb; | 31 | struct super_block *sb = inode->i_sb; |
| 32 | struct udf_sb_info *sbi = UDF_SB(sb); | 32 | struct udf_sb_info *sbi = UDF_SB(sb); |
| 33 | struct logicalVolIntegrityDescImpUse *lvidiu = udf_sb_lvidiu(sb); | ||
| 33 | 34 | ||
| 34 | mutex_lock(&sbi->s_alloc_mutex); | 35 | if (lvidiu) { |
| 35 | if (sbi->s_lvid_bh) { | 36 | mutex_lock(&sbi->s_alloc_mutex); |
| 36 | struct logicalVolIntegrityDescImpUse *lvidiu = | ||
| 37 | udf_sb_lvidiu(sbi); | ||
| 38 | if (S_ISDIR(inode->i_mode)) | 37 | if (S_ISDIR(inode->i_mode)) |
| 39 | le32_add_cpu(&lvidiu->numDirs, -1); | 38 | le32_add_cpu(&lvidiu->numDirs, -1); |
| 40 | else | 39 | else |
| 41 | le32_add_cpu(&lvidiu->numFiles, -1); | 40 | le32_add_cpu(&lvidiu->numFiles, -1); |
| 42 | udf_updated_lvid(sb); | 41 | udf_updated_lvid(sb); |
| 42 | mutex_unlock(&sbi->s_alloc_mutex); | ||
| 43 | } | 43 | } |
| 44 | mutex_unlock(&sbi->s_alloc_mutex); | ||
| 45 | 44 | ||
| 46 | udf_free_blocks(sb, NULL, &UDF_I(inode)->i_location, 0, 1); | 45 | udf_free_blocks(sb, NULL, &UDF_I(inode)->i_location, 0, 1); |
| 47 | } | 46 | } |
| @@ -55,6 +54,7 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode, int *err) | |||
| 55 | uint32_t start = UDF_I(dir)->i_location.logicalBlockNum; | 54 | uint32_t start = UDF_I(dir)->i_location.logicalBlockNum; |
| 56 | struct udf_inode_info *iinfo; | 55 | struct udf_inode_info *iinfo; |
| 57 | struct udf_inode_info *dinfo = UDF_I(dir); | 56 | struct udf_inode_info *dinfo = UDF_I(dir); |
| 57 | struct logicalVolIntegrityDescImpUse *lvidiu; | ||
| 58 | 58 | ||
| 59 | inode = new_inode(sb); | 59 | inode = new_inode(sb); |
| 60 | 60 | ||
| @@ -92,12 +92,10 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode, int *err) | |||
| 92 | return NULL; | 92 | return NULL; |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | if (sbi->s_lvid_bh) { | 95 | lvidiu = udf_sb_lvidiu(sb); |
| 96 | struct logicalVolIntegrityDescImpUse *lvidiu; | 96 | if (lvidiu) { |
| 97 | |||
| 98 | iinfo->i_unique = lvid_get_unique_id(sb); | 97 | iinfo->i_unique = lvid_get_unique_id(sb); |
| 99 | mutex_lock(&sbi->s_alloc_mutex); | 98 | mutex_lock(&sbi->s_alloc_mutex); |
| 100 | lvidiu = udf_sb_lvidiu(sbi); | ||
| 101 | if (S_ISDIR(mode)) | 99 | if (S_ISDIR(mode)) |
| 102 | le32_add_cpu(&lvidiu->numDirs, 1); | 100 | le32_add_cpu(&lvidiu->numDirs, 1); |
| 103 | else | 101 | else |
diff --git a/fs/udf/super.c b/fs/udf/super.c index 839a2bad7f45..91219385691d 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
| @@ -94,13 +94,25 @@ static unsigned int udf_count_free(struct super_block *); | |||
| 94 | static int udf_statfs(struct dentry *, struct kstatfs *); | 94 | static int udf_statfs(struct dentry *, struct kstatfs *); |
| 95 | static int udf_show_options(struct seq_file *, struct dentry *); | 95 | static int udf_show_options(struct seq_file *, struct dentry *); |
| 96 | 96 | ||
| 97 | struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct udf_sb_info *sbi) | 97 | struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct super_block *sb) |
| 98 | { | 98 | { |
| 99 | struct logicalVolIntegrityDesc *lvid = | 99 | struct logicalVolIntegrityDesc *lvid; |
| 100 | (struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data; | 100 | unsigned int partnum; |
| 101 | __u32 number_of_partitions = le32_to_cpu(lvid->numOfPartitions); | 101 | unsigned int offset; |
| 102 | __u32 offset = number_of_partitions * 2 * | 102 | |
| 103 | sizeof(uint32_t)/sizeof(uint8_t); | 103 | if (!UDF_SB(sb)->s_lvid_bh) |
| 104 | return NULL; | ||
| 105 | lvid = (struct logicalVolIntegrityDesc *)UDF_SB(sb)->s_lvid_bh->b_data; | ||
| 106 | partnum = le32_to_cpu(lvid->numOfPartitions); | ||
| 107 | if ((sb->s_blocksize - sizeof(struct logicalVolIntegrityDescImpUse) - | ||
| 108 | offsetof(struct logicalVolIntegrityDesc, impUse)) / | ||
| 109 | (2 * sizeof(uint32_t)) < partnum) { | ||
| 110 | udf_err(sb, "Logical volume integrity descriptor corrupted " | ||
| 111 | "(numOfPartitions = %u)!\n", partnum); | ||
| 112 | return NULL; | ||
| 113 | } | ||
| 114 | /* The offset is to skip freeSpaceTable and sizeTable arrays */ | ||
| 115 | offset = partnum * 2 * sizeof(uint32_t); | ||
| 104 | return (struct logicalVolIntegrityDescImpUse *)&(lvid->impUse[offset]); | 116 | return (struct logicalVolIntegrityDescImpUse *)&(lvid->impUse[offset]); |
| 105 | } | 117 | } |
| 106 | 118 | ||
| @@ -629,9 +641,10 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options) | |||
| 629 | struct udf_options uopt; | 641 | struct udf_options uopt; |
| 630 | struct udf_sb_info *sbi = UDF_SB(sb); | 642 | struct udf_sb_info *sbi = UDF_SB(sb); |
| 631 | int error = 0; | 643 | int error = 0; |
| 644 | struct logicalVolIntegrityDescImpUse *lvidiu = udf_sb_lvidiu(sb); | ||
| 632 | 645 | ||
| 633 | if (sbi->s_lvid_bh) { | 646 | if (lvidiu) { |
| 634 | int write_rev = le16_to_cpu(udf_sb_lvidiu(sbi)->minUDFWriteRev); | 647 | int write_rev = le16_to_cpu(lvidiu->minUDFWriteRev); |
| 635 | if (write_rev > UDF_MAX_WRITE_VERSION && !(*flags & MS_RDONLY)) | 648 | if (write_rev > UDF_MAX_WRITE_VERSION && !(*flags & MS_RDONLY)) |
| 636 | return -EACCES; | 649 | return -EACCES; |
| 637 | } | 650 | } |
| @@ -1905,11 +1918,12 @@ static void udf_open_lvid(struct super_block *sb) | |||
| 1905 | 1918 | ||
| 1906 | if (!bh) | 1919 | if (!bh) |
| 1907 | return; | 1920 | return; |
| 1908 | |||
| 1909 | mutex_lock(&sbi->s_alloc_mutex); | ||
| 1910 | lvid = (struct logicalVolIntegrityDesc *)bh->b_data; | 1921 | lvid = (struct logicalVolIntegrityDesc *)bh->b_data; |
| 1911 | lvidiu = udf_sb_lvidiu(sbi); | 1922 | lvidiu = udf_sb_lvidiu(sb); |
| 1923 | if (!lvidiu) | ||
| 1924 | return; | ||
| 1912 | 1925 | ||
| 1926 | mutex_lock(&sbi->s_alloc_mutex); | ||
| 1913 | lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; | 1927 | lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; |
| 1914 | lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; | 1928 | lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; |
| 1915 | udf_time_to_disk_stamp(&lvid->recordingDateAndTime, | 1929 | udf_time_to_disk_stamp(&lvid->recordingDateAndTime, |
| @@ -1937,10 +1951,12 @@ static void udf_close_lvid(struct super_block *sb) | |||
| 1937 | 1951 | ||
| 1938 | if (!bh) | 1952 | if (!bh) |
| 1939 | return; | 1953 | return; |
| 1954 | lvid = (struct logicalVolIntegrityDesc *)bh->b_data; | ||
| 1955 | lvidiu = udf_sb_lvidiu(sb); | ||
| 1956 | if (!lvidiu) | ||
| 1957 | return; | ||
| 1940 | 1958 | ||
| 1941 | mutex_lock(&sbi->s_alloc_mutex); | 1959 | mutex_lock(&sbi->s_alloc_mutex); |
| 1942 | lvid = (struct logicalVolIntegrityDesc *)bh->b_data; | ||
| 1943 | lvidiu = udf_sb_lvidiu(sbi); | ||
| 1944 | lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; | 1960 | lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; |
| 1945 | lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; | 1961 | lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; |
| 1946 | udf_time_to_disk_stamp(&lvid->recordingDateAndTime, CURRENT_TIME); | 1962 | udf_time_to_disk_stamp(&lvid->recordingDateAndTime, CURRENT_TIME); |
| @@ -2093,15 +2109,19 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) | |||
| 2093 | 2109 | ||
| 2094 | if (sbi->s_lvid_bh) { | 2110 | if (sbi->s_lvid_bh) { |
| 2095 | struct logicalVolIntegrityDescImpUse *lvidiu = | 2111 | struct logicalVolIntegrityDescImpUse *lvidiu = |
| 2096 | udf_sb_lvidiu(sbi); | 2112 | udf_sb_lvidiu(sb); |
| 2097 | uint16_t minUDFReadRev = le16_to_cpu(lvidiu->minUDFReadRev); | 2113 | uint16_t minUDFReadRev; |
| 2098 | uint16_t minUDFWriteRev = le16_to_cpu(lvidiu->minUDFWriteRev); | 2114 | uint16_t minUDFWriteRev; |
| 2099 | /* uint16_t maxUDFWriteRev = | ||
| 2100 | le16_to_cpu(lvidiu->maxUDFWriteRev); */ | ||
| 2101 | 2115 | ||
| 2116 | if (!lvidiu) { | ||
| 2117 | ret = -EINVAL; | ||
| 2118 | goto error_out; | ||
| 2119 | } | ||
| 2120 | minUDFReadRev = le16_to_cpu(lvidiu->minUDFReadRev); | ||
| 2121 | minUDFWriteRev = le16_to_cpu(lvidiu->minUDFWriteRev); | ||
| 2102 | if (minUDFReadRev > UDF_MAX_READ_VERSION) { | 2122 | if (minUDFReadRev > UDF_MAX_READ_VERSION) { |
| 2103 | udf_err(sb, "minUDFReadRev=%x (max is %x)\n", | 2123 | udf_err(sb, "minUDFReadRev=%x (max is %x)\n", |
| 2104 | le16_to_cpu(lvidiu->minUDFReadRev), | 2124 | minUDFReadRev, |
| 2105 | UDF_MAX_READ_VERSION); | 2125 | UDF_MAX_READ_VERSION); |
| 2106 | ret = -EINVAL; | 2126 | ret = -EINVAL; |
| 2107 | goto error_out; | 2127 | goto error_out; |
| @@ -2265,11 +2285,7 @@ static int udf_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
| 2265 | struct logicalVolIntegrityDescImpUse *lvidiu; | 2285 | struct logicalVolIntegrityDescImpUse *lvidiu; |
| 2266 | u64 id = huge_encode_dev(sb->s_bdev->bd_dev); | 2286 | u64 id = huge_encode_dev(sb->s_bdev->bd_dev); |
| 2267 | 2287 | ||
| 2268 | if (sbi->s_lvid_bh != NULL) | 2288 | lvidiu = udf_sb_lvidiu(sb); |
| 2269 | lvidiu = udf_sb_lvidiu(sbi); | ||
| 2270 | else | ||
| 2271 | lvidiu = NULL; | ||
| 2272 | |||
| 2273 | buf->f_type = UDF_SUPER_MAGIC; | 2289 | buf->f_type = UDF_SUPER_MAGIC; |
| 2274 | buf->f_bsize = sb->s_blocksize; | 2290 | buf->f_bsize = sb->s_blocksize; |
| 2275 | buf->f_blocks = sbi->s_partmaps[sbi->s_partition].s_partition_len; | 2291 | buf->f_blocks = sbi->s_partmaps[sbi->s_partition].s_partition_len; |
diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h index ed401e94aa8c..1f32c7bd9f57 100644 --- a/fs/udf/udf_sb.h +++ b/fs/udf/udf_sb.h | |||
| @@ -162,7 +162,7 @@ static inline struct udf_sb_info *UDF_SB(struct super_block *sb) | |||
| 162 | return sb->s_fs_info; | 162 | return sb->s_fs_info; |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct udf_sb_info *sbi); | 165 | struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct super_block *sb); |
| 166 | 166 | ||
| 167 | int udf_compute_nr_groups(struct super_block *sb, u32 partition); | 167 | int udf_compute_nr_groups(struct super_block *sb, u32 partition); |
| 168 | 168 | ||
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 88c5ea75ebf6..f1d85cfc0a54 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c | |||
| @@ -628,6 +628,7 @@ xfs_buf_item_unlock( | |||
| 628 | else if (aborted) { | 628 | else if (aborted) { |
| 629 | ASSERT(XFS_FORCED_SHUTDOWN(lip->li_mountp)); | 629 | ASSERT(XFS_FORCED_SHUTDOWN(lip->li_mountp)); |
| 630 | if (lip->li_flags & XFS_LI_IN_AIL) { | 630 | if (lip->li_flags & XFS_LI_IN_AIL) { |
| 631 | spin_lock(&lip->li_ailp->xa_lock); | ||
| 631 | xfs_trans_ail_delete(lip->li_ailp, lip, | 632 | xfs_trans_ail_delete(lip->li_ailp, lip, |
| 632 | SHUTDOWN_LOG_IO_ERROR); | 633 | SHUTDOWN_LOG_IO_ERROR); |
| 633 | } | 634 | } |
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 069537c845e5..20bf8e8002d6 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c | |||
| @@ -1224,6 +1224,7 @@ xfs_da3_node_toosmall( | |||
| 1224 | /* start with smaller blk num */ | 1224 | /* start with smaller blk num */ |
| 1225 | forward = nodehdr.forw < nodehdr.back; | 1225 | forward = nodehdr.forw < nodehdr.back; |
| 1226 | for (i = 0; i < 2; forward = !forward, i++) { | 1226 | for (i = 0; i < 2; forward = !forward, i++) { |
| 1227 | struct xfs_da3_icnode_hdr thdr; | ||
| 1227 | if (forward) | 1228 | if (forward) |
| 1228 | blkno = nodehdr.forw; | 1229 | blkno = nodehdr.forw; |
| 1229 | else | 1230 | else |
| @@ -1236,10 +1237,10 @@ xfs_da3_node_toosmall( | |||
| 1236 | return(error); | 1237 | return(error); |
| 1237 | 1238 | ||
| 1238 | node = bp->b_addr; | 1239 | node = bp->b_addr; |
| 1239 | xfs_da3_node_hdr_from_disk(&nodehdr, node); | 1240 | xfs_da3_node_hdr_from_disk(&thdr, node); |
| 1240 | xfs_trans_brelse(state->args->trans, bp); | 1241 | xfs_trans_brelse(state->args->trans, bp); |
| 1241 | 1242 | ||
| 1242 | if (count - nodehdr.count >= 0) | 1243 | if (count - thdr.count >= 0) |
| 1243 | break; /* fits with at least 25% to spare */ | 1244 | break; /* fits with at least 25% to spare */ |
| 1244 | } | 1245 | } |
| 1245 | if (i >= 2) { | 1246 | if (i >= 2) { |
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 0957aa98b6c0..12dad188939d 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c | |||
| @@ -1158,7 +1158,7 @@ xfs_dir2_sf_to_block( | |||
| 1158 | /* | 1158 | /* |
| 1159 | * Create entry for . | 1159 | * Create entry for . |
| 1160 | */ | 1160 | */ |
| 1161 | dep = xfs_dir3_data_dot_entry_p(hdr); | 1161 | dep = xfs_dir3_data_dot_entry_p(mp, hdr); |
| 1162 | dep->inumber = cpu_to_be64(dp->i_ino); | 1162 | dep->inumber = cpu_to_be64(dp->i_ino); |
| 1163 | dep->namelen = 1; | 1163 | dep->namelen = 1; |
| 1164 | dep->name[0] = '.'; | 1164 | dep->name[0] = '.'; |
| @@ -1172,7 +1172,7 @@ xfs_dir2_sf_to_block( | |||
| 1172 | /* | 1172 | /* |
| 1173 | * Create entry for .. | 1173 | * Create entry for .. |
| 1174 | */ | 1174 | */ |
| 1175 | dep = xfs_dir3_data_dotdot_entry_p(hdr); | 1175 | dep = xfs_dir3_data_dotdot_entry_p(mp, hdr); |
| 1176 | dep->inumber = cpu_to_be64(xfs_dir2_sf_get_parent_ino(sfp)); | 1176 | dep->inumber = cpu_to_be64(xfs_dir2_sf_get_parent_ino(sfp)); |
| 1177 | dep->namelen = 2; | 1177 | dep->namelen = 2; |
| 1178 | dep->name[0] = dep->name[1] = '.'; | 1178 | dep->name[0] = dep->name[1] = '.'; |
| @@ -1183,7 +1183,7 @@ xfs_dir2_sf_to_block( | |||
| 1183 | blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot); | 1183 | blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot); |
| 1184 | blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp, | 1184 | blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp, |
| 1185 | (char *)dep - (char *)hdr)); | 1185 | (char *)dep - (char *)hdr)); |
| 1186 | offset = xfs_dir3_data_first_offset(hdr); | 1186 | offset = xfs_dir3_data_first_offset(mp); |
| 1187 | /* | 1187 | /* |
| 1188 | * Loop over existing entries, stuff them in. | 1188 | * Loop over existing entries, stuff them in. |
| 1189 | */ | 1189 | */ |
diff --git a/fs/xfs/xfs_dir2_format.h b/fs/xfs/xfs_dir2_format.h index a0961a61ac1a..9cf67381adf6 100644 --- a/fs/xfs/xfs_dir2_format.h +++ b/fs/xfs/xfs_dir2_format.h | |||
| @@ -497,69 +497,58 @@ xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr) | |||
| 497 | /* | 497 | /* |
| 498 | * Offsets of . and .. in data space (always block 0) | 498 | * Offsets of . and .. in data space (always block 0) |
| 499 | * | 499 | * |
| 500 | * The macros are used for shortform directories as they have no headers to read | ||
| 501 | * the magic number out of. Shortform directories need to know the size of the | ||
| 502 | * data block header because the sfe embeds the block offset of the entry into | ||
| 503 | * it so that it doesn't change when format conversion occurs. Bad Things Happen | ||
| 504 | * if we don't follow this rule. | ||
| 505 | * | ||
| 506 | * XXX: there is scope for significant optimisation of the logic here. Right | 500 | * XXX: there is scope for significant optimisation of the logic here. Right |
| 507 | * now we are checking for "dir3 format" over and over again. Ideally we should | 501 | * now we are checking for "dir3 format" over and over again. Ideally we should |
| 508 | * only do it once for each operation. | 502 | * only do it once for each operation. |
| 509 | */ | 503 | */ |
| 510 | #define XFS_DIR3_DATA_DOT_OFFSET(mp) \ | ||
| 511 | xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&(mp)->m_sb)) | ||
| 512 | #define XFS_DIR3_DATA_DOTDOT_OFFSET(mp) \ | ||
| 513 | (XFS_DIR3_DATA_DOT_OFFSET(mp) + xfs_dir3_data_entsize(mp, 1)) | ||
| 514 | #define XFS_DIR3_DATA_FIRST_OFFSET(mp) \ | ||
| 515 | (XFS_DIR3_DATA_DOTDOT_OFFSET(mp) + xfs_dir3_data_entsize(mp, 2)) | ||
| 516 | |||
| 517 | static inline xfs_dir2_data_aoff_t | 504 | static inline xfs_dir2_data_aoff_t |
| 518 | xfs_dir3_data_dot_offset(struct xfs_dir2_data_hdr *hdr) | 505 | xfs_dir3_data_dot_offset(struct xfs_mount *mp) |
| 519 | { | 506 | { |
| 520 | return xfs_dir3_data_entry_offset(hdr); | 507 | return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb)); |
| 521 | } | 508 | } |
| 522 | 509 | ||
| 523 | static inline xfs_dir2_data_aoff_t | 510 | static inline xfs_dir2_data_aoff_t |
| 524 | xfs_dir3_data_dotdot_offset(struct xfs_dir2_data_hdr *hdr) | 511 | xfs_dir3_data_dotdot_offset(struct xfs_mount *mp) |
| 525 | { | 512 | { |
| 526 | bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || | 513 | return xfs_dir3_data_dot_offset(mp) + |
| 527 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC); | 514 | xfs_dir3_data_entsize(mp, 1); |
| 528 | return xfs_dir3_data_dot_offset(hdr) + | ||
| 529 | __xfs_dir3_data_entsize(dir3, 1); | ||
| 530 | } | 515 | } |
| 531 | 516 | ||
| 532 | static inline xfs_dir2_data_aoff_t | 517 | static inline xfs_dir2_data_aoff_t |
| 533 | xfs_dir3_data_first_offset(struct xfs_dir2_data_hdr *hdr) | 518 | xfs_dir3_data_first_offset(struct xfs_mount *mp) |
| 534 | { | 519 | { |
| 535 | bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || | 520 | return xfs_dir3_data_dotdot_offset(mp) + |
| 536 | hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC); | 521 | xfs_dir3_data_entsize(mp, 2); |
| 537 | return xfs_dir3_data_dotdot_offset(hdr) + | ||
| 538 | __xfs_dir3_data_entsize(dir3, 2); | ||
| 539 | } | 522 | } |
| 540 | 523 | ||
| 541 | /* | 524 | /* |
| 542 | * location of . and .. in data space (always block 0) | 525 | * location of . and .. in data space (always block 0) |
| 543 | */ | 526 | */ |
| 544 | static inline struct xfs_dir2_data_entry * | 527 | static inline struct xfs_dir2_data_entry * |
| 545 | xfs_dir3_data_dot_entry_p(struct xfs_dir2_data_hdr *hdr) | 528 | xfs_dir3_data_dot_entry_p( |
| 529 | struct xfs_mount *mp, | ||
| 530 | struct xfs_dir2_data_hdr *hdr) | ||
| 546 | { | 531 | { |
| 547 | return (struct xfs_dir2_data_entry *) | 532 | return (struct xfs_dir2_data_entry *) |
| 548 | ((char *)hdr + xfs_dir3_data_dot_offset(hdr)); | 533 | ((char *)hdr + xfs_dir3_data_dot_offset(mp)); |
| 549 | } | 534 | } |
| 550 | 535 | ||
| 551 | static inline struct xfs_dir2_data_entry * | 536 | static inline struct xfs_dir2_data_entry * |
| 552 | xfs_dir3_data_dotdot_entry_p(struct xfs_dir2_data_hdr *hdr) | 537 | xfs_dir3_data_dotdot_entry_p( |
| 538 | struct xfs_mount *mp, | ||
| 539 | struct xfs_dir2_data_hdr *hdr) | ||
| 553 | { | 540 | { |
| 554 | return (struct xfs_dir2_data_entry *) | 541 | return (struct xfs_dir2_data_entry *) |
| 555 | ((char *)hdr + xfs_dir3_data_dotdot_offset(hdr)); | 542 | ((char *)hdr + xfs_dir3_data_dotdot_offset(mp)); |
| 556 | } | 543 | } |
| 557 | 544 | ||
| 558 | static inline struct xfs_dir2_data_entry * | 545 | static inline struct xfs_dir2_data_entry * |
| 559 | xfs_dir3_data_first_entry_p(struct xfs_dir2_data_hdr *hdr) | 546 | xfs_dir3_data_first_entry_p( |
| 547 | struct xfs_mount *mp, | ||
| 548 | struct xfs_dir2_data_hdr *hdr) | ||
| 560 | { | 549 | { |
| 561 | return (struct xfs_dir2_data_entry *) | 550 | return (struct xfs_dir2_data_entry *) |
| 562 | ((char *)hdr + xfs_dir3_data_first_offset(hdr)); | 551 | ((char *)hdr + xfs_dir3_data_first_offset(mp)); |
| 563 | } | 552 | } |
| 564 | 553 | ||
| 565 | /* | 554 | /* |
diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c index 8993ec17452c..8f84153e98a8 100644 --- a/fs/xfs/xfs_dir2_readdir.c +++ b/fs/xfs/xfs_dir2_readdir.c | |||
| @@ -119,9 +119,9 @@ xfs_dir2_sf_getdents( | |||
| 119 | * mp->m_dirdatablk. | 119 | * mp->m_dirdatablk. |
| 120 | */ | 120 | */ |
| 121 | dot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, | 121 | dot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, |
| 122 | XFS_DIR3_DATA_DOT_OFFSET(mp)); | 122 | xfs_dir3_data_dot_offset(mp)); |
| 123 | dotdot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, | 123 | dotdot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, |
| 124 | XFS_DIR3_DATA_DOTDOT_OFFSET(mp)); | 124 | xfs_dir3_data_dotdot_offset(mp)); |
| 125 | 125 | ||
| 126 | /* | 126 | /* |
| 127 | * Put . entry unless we're starting past it. | 127 | * Put . entry unless we're starting past it. |
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index bb6e2848f473..3ef6d402084c 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c | |||
| @@ -557,7 +557,7 @@ xfs_dir2_sf_addname_hard( | |||
| 557 | * to insert the new entry. | 557 | * to insert the new entry. |
| 558 | * If it's going to end up at the end then oldsfep will point there. | 558 | * If it's going to end up at the end then oldsfep will point there. |
| 559 | */ | 559 | */ |
| 560 | for (offset = XFS_DIR3_DATA_FIRST_OFFSET(mp), | 560 | for (offset = xfs_dir3_data_first_offset(mp), |
| 561 | oldsfep = xfs_dir2_sf_firstentry(oldsfp), | 561 | oldsfep = xfs_dir2_sf_firstentry(oldsfp), |
| 562 | add_datasize = xfs_dir3_data_entsize(mp, args->namelen), | 562 | add_datasize = xfs_dir3_data_entsize(mp, args->namelen), |
| 563 | eof = (char *)oldsfep == &buf[old_isize]; | 563 | eof = (char *)oldsfep == &buf[old_isize]; |
| @@ -640,7 +640,7 @@ xfs_dir2_sf_addname_pick( | |||
| 640 | 640 | ||
| 641 | sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; | 641 | sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; |
| 642 | size = xfs_dir3_data_entsize(mp, args->namelen); | 642 | size = xfs_dir3_data_entsize(mp, args->namelen); |
| 643 | offset = XFS_DIR3_DATA_FIRST_OFFSET(mp); | 643 | offset = xfs_dir3_data_first_offset(mp); |
| 644 | sfep = xfs_dir2_sf_firstentry(sfp); | 644 | sfep = xfs_dir2_sf_firstentry(sfp); |
| 645 | holefit = 0; | 645 | holefit = 0; |
| 646 | /* | 646 | /* |
| @@ -713,7 +713,7 @@ xfs_dir2_sf_check( | |||
| 713 | mp = dp->i_mount; | 713 | mp = dp->i_mount; |
| 714 | 714 | ||
| 715 | sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; | 715 | sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; |
| 716 | offset = XFS_DIR3_DATA_FIRST_OFFSET(mp); | 716 | offset = xfs_dir3_data_first_offset(mp); |
| 717 | ino = xfs_dir2_sf_get_parent_ino(sfp); | 717 | ino = xfs_dir2_sf_get_parent_ino(sfp); |
| 718 | i8count = ino > XFS_DIR2_MAX_SHORT_INUM; | 718 | i8count = ino > XFS_DIR2_MAX_SHORT_INUM; |
| 719 | 719 | ||
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index 71520e6e5d65..1ee776d477c3 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c | |||
| @@ -64,7 +64,8 @@ int xfs_dqerror_mod = 33; | |||
| 64 | struct kmem_zone *xfs_qm_dqtrxzone; | 64 | struct kmem_zone *xfs_qm_dqtrxzone; |
| 65 | static struct kmem_zone *xfs_qm_dqzone; | 65 | static struct kmem_zone *xfs_qm_dqzone; |
| 66 | 66 | ||
| 67 | static struct lock_class_key xfs_dquot_other_class; | 67 | static struct lock_class_key xfs_dquot_group_class; |
| 68 | static struct lock_class_key xfs_dquot_project_class; | ||
| 68 | 69 | ||
| 69 | /* | 70 | /* |
| 70 | * This is called to free all the memory associated with a dquot | 71 | * This is called to free all the memory associated with a dquot |
| @@ -703,8 +704,20 @@ xfs_qm_dqread( | |||
| 703 | * Make sure group quotas have a different lock class than user | 704 | * Make sure group quotas have a different lock class than user |
| 704 | * quotas. | 705 | * quotas. |
| 705 | */ | 706 | */ |
| 706 | if (!(type & XFS_DQ_USER)) | 707 | switch (type) { |
| 707 | lockdep_set_class(&dqp->q_qlock, &xfs_dquot_other_class); | 708 | case XFS_DQ_USER: |
| 709 | /* uses the default lock class */ | ||
| 710 | break; | ||
| 711 | case XFS_DQ_GROUP: | ||
| 712 | lockdep_set_class(&dqp->q_qlock, &xfs_dquot_group_class); | ||
| 713 | break; | ||
| 714 | case XFS_DQ_PROJ: | ||
| 715 | lockdep_set_class(&dqp->q_qlock, &xfs_dquot_project_class); | ||
| 716 | break; | ||
| 717 | default: | ||
| 718 | ASSERT(0); | ||
| 719 | break; | ||
| 720 | } | ||
| 708 | 721 | ||
| 709 | XFS_STATS_INC(xs_qm_dquot); | 722 | XFS_STATS_INC(xs_qm_dquot); |
| 710 | 723 | ||
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h index 1edb5cc3e5f4..18272c766a50 100644 --- a/fs/xfs/xfs_fs.h +++ b/fs/xfs/xfs_fs.h | |||
| @@ -515,7 +515,7 @@ typedef struct xfs_swapext | |||
| 515 | /* XFS_IOC_GETBIOSIZE ---- deprecated 47 */ | 515 | /* XFS_IOC_GETBIOSIZE ---- deprecated 47 */ |
| 516 | #define XFS_IOC_GETBMAPX _IOWR('X', 56, struct getbmap) | 516 | #define XFS_IOC_GETBMAPX _IOWR('X', 56, struct getbmap) |
| 517 | #define XFS_IOC_ZERO_RANGE _IOW ('X', 57, struct xfs_flock64) | 517 | #define XFS_IOC_ZERO_RANGE _IOW ('X', 57, struct xfs_flock64) |
| 518 | #define XFS_IOC_FREE_EOFBLOCKS _IOR ('X', 58, struct xfs_eofblocks) | 518 | #define XFS_IOC_FREE_EOFBLOCKS _IOR ('X', 58, struct xfs_fs_eofblocks) |
| 519 | 519 | ||
| 520 | /* | 520 | /* |
| 521 | * ioctl commands that replace IRIX syssgi()'s | 521 | * ioctl commands that replace IRIX syssgi()'s |
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 193206ba4358..474807a401c8 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c | |||
| @@ -119,11 +119,6 @@ xfs_inode_free( | |||
| 119 | ip->i_itemp = NULL; | 119 | ip->i_itemp = NULL; |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | /* asserts to verify all state is correct here */ | ||
| 123 | ASSERT(atomic_read(&ip->i_pincount) == 0); | ||
| 124 | ASSERT(!spin_is_locked(&ip->i_flags_lock)); | ||
| 125 | ASSERT(!xfs_isiflocked(ip)); | ||
| 126 | |||
| 127 | /* | 122 | /* |
| 128 | * Because we use RCU freeing we need to ensure the inode always | 123 | * Because we use RCU freeing we need to ensure the inode always |
| 129 | * appears to be reclaimed with an invalid inode number when in the | 124 | * appears to be reclaimed with an invalid inode number when in the |
| @@ -135,6 +130,10 @@ xfs_inode_free( | |||
| 135 | ip->i_ino = 0; | 130 | ip->i_ino = 0; |
| 136 | spin_unlock(&ip->i_flags_lock); | 131 | spin_unlock(&ip->i_flags_lock); |
| 137 | 132 | ||
| 133 | /* asserts to verify all state is correct here */ | ||
| 134 | ASSERT(atomic_read(&ip->i_pincount) == 0); | ||
| 135 | ASSERT(!xfs_isiflocked(ip)); | ||
| 136 | |||
| 138 | call_rcu(&VFS_I(ip)->i_rcu, xfs_inode_free_callback); | 137 | call_rcu(&VFS_I(ip)->i_rcu, xfs_inode_free_callback); |
| 139 | } | 138 | } |
| 140 | 139 | ||
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index dabda9521b4b..39797490a1f1 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
| @@ -1585,6 +1585,7 @@ xlog_recover_add_to_trans( | |||
| 1585 | "bad number of regions (%d) in inode log format", | 1585 | "bad number of regions (%d) in inode log format", |
| 1586 | in_f->ilf_size); | 1586 | in_f->ilf_size); |
| 1587 | ASSERT(0); | 1587 | ASSERT(0); |
| 1588 | kmem_free(ptr); | ||
| 1588 | return XFS_ERROR(EIO); | 1589 | return XFS_ERROR(EIO); |
| 1589 | } | 1590 | } |
| 1590 | 1591 | ||
| @@ -1970,6 +1971,13 @@ xlog_recover_do_inode_buffer( | |||
| 1970 | * magic number. If we don't recognise the magic number in the buffer, then | 1971 | * magic number. If we don't recognise the magic number in the buffer, then |
| 1971 | * return a LSN of -1 so that the caller knows it was an unrecognised block and | 1972 | * return a LSN of -1 so that the caller knows it was an unrecognised block and |
| 1972 | * so can recover the buffer. | 1973 | * so can recover the buffer. |
| 1974 | * | ||
| 1975 | * Note: we cannot rely solely on magic number matches to determine that the | ||
| 1976 | * buffer has a valid LSN - we also need to verify that it belongs to this | ||
| 1977 | * filesystem, so we need to extract the object's LSN and compare it to that | ||
| 1978 | * which we read from the superblock. If the UUIDs don't match, then we've got a | ||
| 1979 | * stale metadata block from an old filesystem instance that we need to recover | ||
| 1980 | * over the top of. | ||
| 1973 | */ | 1981 | */ |
| 1974 | static xfs_lsn_t | 1982 | static xfs_lsn_t |
| 1975 | xlog_recover_get_buf_lsn( | 1983 | xlog_recover_get_buf_lsn( |
| @@ -1980,6 +1988,8 @@ xlog_recover_get_buf_lsn( | |||
| 1980 | __uint16_t magic16; | 1988 | __uint16_t magic16; |
| 1981 | __uint16_t magicda; | 1989 | __uint16_t magicda; |
| 1982 | void *blk = bp->b_addr; | 1990 | void *blk = bp->b_addr; |
| 1991 | uuid_t *uuid; | ||
| 1992 | xfs_lsn_t lsn = -1; | ||
| 1983 | 1993 | ||
| 1984 | /* v4 filesystems always recover immediately */ | 1994 | /* v4 filesystems always recover immediately */ |
| 1985 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | 1995 | if (!xfs_sb_version_hascrc(&mp->m_sb)) |
| @@ -1992,43 +2002,79 @@ xlog_recover_get_buf_lsn( | |||
| 1992 | case XFS_ABTB_MAGIC: | 2002 | case XFS_ABTB_MAGIC: |
| 1993 | case XFS_ABTC_MAGIC: | 2003 | case XFS_ABTC_MAGIC: |
| 1994 | case XFS_IBT_CRC_MAGIC: | 2004 | case XFS_IBT_CRC_MAGIC: |
| 1995 | case XFS_IBT_MAGIC: | 2005 | case XFS_IBT_MAGIC: { |
| 1996 | return be64_to_cpu( | 2006 | struct xfs_btree_block *btb = blk; |
| 1997 | ((struct xfs_btree_block *)blk)->bb_u.s.bb_lsn); | 2007 | |
| 2008 | lsn = be64_to_cpu(btb->bb_u.s.bb_lsn); | ||
| 2009 | uuid = &btb->bb_u.s.bb_uuid; | ||
| 2010 | break; | ||
| 2011 | } | ||
| 1998 | case XFS_BMAP_CRC_MAGIC: | 2012 | case XFS_BMAP_CRC_MAGIC: |
| 1999 | case XFS_BMAP_MAGIC: | 2013 | case XFS_BMAP_MAGIC: { |
| 2000 | return be64_to_cpu( | 2014 | struct xfs_btree_block *btb = blk; |
| 2001 | ((struct xfs_btree_block *)blk)->bb_u.l.bb_lsn); | 2015 | |
| 2016 | lsn = be64_to_cpu(btb->bb_u.l.bb_lsn); | ||
| 2017 | uuid = &btb->bb_u.l.bb_uuid; | ||
| 2018 | break; | ||
| 2019 | } | ||
| 2002 | case XFS_AGF_MAGIC: | 2020 | case XFS_AGF_MAGIC: |
| 2003 | return be64_to_cpu(((struct xfs_agf *)blk)->agf_lsn); | 2021 | lsn = be64_to_cpu(((struct xfs_agf *)blk)->agf_lsn); |
| 2022 | uuid = &((struct xfs_agf *)blk)->agf_uuid; | ||
| 2023 | break; | ||
| 2004 | case XFS_AGFL_MAGIC: | 2024 | case XFS_AGFL_MAGIC: |
| 2005 | return be64_to_cpu(((struct xfs_agfl *)blk)->agfl_lsn); | 2025 | lsn = be64_to_cpu(((struct xfs_agfl *)blk)->agfl_lsn); |
| 2026 | uuid = &((struct xfs_agfl *)blk)->agfl_uuid; | ||
| 2027 | break; | ||
| 2006 | case XFS_AGI_MAGIC: | 2028 | case XFS_AGI_MAGIC: |
| 2007 | return be64_to_cpu(((struct xfs_agi *)blk)->agi_lsn); | 2029 | lsn = be64_to_cpu(((struct xfs_agi *)blk)->agi_lsn); |
| 2030 | uuid = &((struct xfs_agi *)blk)->agi_uuid; | ||
| 2031 | break; | ||
| 2008 | case XFS_SYMLINK_MAGIC: | 2032 | case XFS_SYMLINK_MAGIC: |
| 2009 | return be64_to_cpu(((struct xfs_dsymlink_hdr *)blk)->sl_lsn); | 2033 | lsn = be64_to_cpu(((struct xfs_dsymlink_hdr *)blk)->sl_lsn); |
| 2034 | uuid = &((struct xfs_dsymlink_hdr *)blk)->sl_uuid; | ||
| 2035 | break; | ||
| 2010 | case XFS_DIR3_BLOCK_MAGIC: | 2036 | case XFS_DIR3_BLOCK_MAGIC: |
| 2011 | case XFS_DIR3_DATA_MAGIC: | 2037 | case XFS_DIR3_DATA_MAGIC: |
| 2012 | case XFS_DIR3_FREE_MAGIC: | 2038 | case XFS_DIR3_FREE_MAGIC: |
| 2013 | return be64_to_cpu(((struct xfs_dir3_blk_hdr *)blk)->lsn); | 2039 | lsn = be64_to_cpu(((struct xfs_dir3_blk_hdr *)blk)->lsn); |
| 2040 | uuid = &((struct xfs_dir3_blk_hdr *)blk)->uuid; | ||
| 2041 | break; | ||
| 2014 | case XFS_ATTR3_RMT_MAGIC: | 2042 | case XFS_ATTR3_RMT_MAGIC: |
| 2015 | return be64_to_cpu(((struct xfs_attr3_rmt_hdr *)blk)->rm_lsn); | 2043 | lsn = be64_to_cpu(((struct xfs_attr3_rmt_hdr *)blk)->rm_lsn); |
| 2044 | uuid = &((struct xfs_attr3_rmt_hdr *)blk)->rm_uuid; | ||
| 2045 | break; | ||
| 2016 | case XFS_SB_MAGIC: | 2046 | case XFS_SB_MAGIC: |
| 2017 | return be64_to_cpu(((struct xfs_dsb *)blk)->sb_lsn); | 2047 | lsn = be64_to_cpu(((struct xfs_dsb *)blk)->sb_lsn); |
| 2048 | uuid = &((struct xfs_dsb *)blk)->sb_uuid; | ||
| 2049 | break; | ||
| 2018 | default: | 2050 | default: |
| 2019 | break; | 2051 | break; |
| 2020 | } | 2052 | } |
| 2021 | 2053 | ||
| 2054 | if (lsn != (xfs_lsn_t)-1) { | ||
| 2055 | if (!uuid_equal(&mp->m_sb.sb_uuid, uuid)) | ||
| 2056 | goto recover_immediately; | ||
| 2057 | return lsn; | ||
| 2058 | } | ||
| 2059 | |||
| 2022 | magicda = be16_to_cpu(((struct xfs_da_blkinfo *)blk)->magic); | 2060 | magicda = be16_to_cpu(((struct xfs_da_blkinfo *)blk)->magic); |
| 2023 | switch (magicda) { | 2061 | switch (magicda) { |
| 2024 | case XFS_DIR3_LEAF1_MAGIC: | 2062 | case XFS_DIR3_LEAF1_MAGIC: |
| 2025 | case XFS_DIR3_LEAFN_MAGIC: | 2063 | case XFS_DIR3_LEAFN_MAGIC: |
| 2026 | case XFS_DA3_NODE_MAGIC: | 2064 | case XFS_DA3_NODE_MAGIC: |
| 2027 | return be64_to_cpu(((struct xfs_da3_blkinfo *)blk)->lsn); | 2065 | lsn = be64_to_cpu(((struct xfs_da3_blkinfo *)blk)->lsn); |
| 2066 | uuid = &((struct xfs_da3_blkinfo *)blk)->uuid; | ||
| 2067 | break; | ||
| 2028 | default: | 2068 | default: |
| 2029 | break; | 2069 | break; |
| 2030 | } | 2070 | } |
| 2031 | 2071 | ||
| 2072 | if (lsn != (xfs_lsn_t)-1) { | ||
| 2073 | if (!uuid_equal(&mp->m_sb.sb_uuid, uuid)) | ||
| 2074 | goto recover_immediately; | ||
| 2075 | return lsn; | ||
| 2076 | } | ||
| 2077 | |||
| 2032 | /* | 2078 | /* |
| 2033 | * We do individual object checks on dquot and inode buffers as they | 2079 | * We do individual object checks on dquot and inode buffers as they |
| 2034 | * have their own individual LSN records. Also, we could have a stale | 2080 | * have their own individual LSN records. Also, we could have a stale |
