diff options
Diffstat (limited to 'fs')
37 files changed, 324 insertions, 246 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; |
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/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/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_log_recover.c b/fs/xfs/xfs_log_recover.c index cc179878fe41..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 | ||
