diff options
Diffstat (limited to 'fs')
65 files changed, 596 insertions, 424 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/disk-io.c b/fs/btrfs/disk-io.c index 4ae17ed13b32..62176ad89846 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -1561,8 +1561,9 @@ int btrfs_insert_fs_root(struct btrfs_fs_info *fs_info, | |||
1561 | return ret; | 1561 | return ret; |
1562 | } | 1562 | } |
1563 | 1563 | ||
1564 | struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, | 1564 | struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info, |
1565 | struct btrfs_key *location) | 1565 | struct btrfs_key *location, |
1566 | bool check_ref) | ||
1566 | { | 1567 | { |
1567 | struct btrfs_root *root; | 1568 | struct btrfs_root *root; |
1568 | int ret; | 1569 | int ret; |
@@ -1586,7 +1587,7 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, | |||
1586 | again: | 1587 | again: |
1587 | root = btrfs_lookup_fs_root(fs_info, location->objectid); | 1588 | root = btrfs_lookup_fs_root(fs_info, location->objectid); |
1588 | if (root) { | 1589 | if (root) { |
1589 | if (btrfs_root_refs(&root->root_item) == 0) | 1590 | if (check_ref && btrfs_root_refs(&root->root_item) == 0) |
1590 | return ERR_PTR(-ENOENT); | 1591 | return ERR_PTR(-ENOENT); |
1591 | return root; | 1592 | return root; |
1592 | } | 1593 | } |
@@ -1595,7 +1596,7 @@ again: | |||
1595 | if (IS_ERR(root)) | 1596 | if (IS_ERR(root)) |
1596 | return root; | 1597 | return root; |
1597 | 1598 | ||
1598 | if (btrfs_root_refs(&root->root_item) == 0) { | 1599 | if (check_ref && btrfs_root_refs(&root->root_item) == 0) { |
1599 | ret = -ENOENT; | 1600 | ret = -ENOENT; |
1600 | goto fail; | 1601 | goto fail; |
1601 | } | 1602 | } |
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index b71acd6e1e5b..5ce2a7da8b11 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h | |||
@@ -68,8 +68,17 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_root *tree_root, | |||
68 | int btrfs_init_fs_root(struct btrfs_root *root); | 68 | int btrfs_init_fs_root(struct btrfs_root *root); |
69 | int btrfs_insert_fs_root(struct btrfs_fs_info *fs_info, | 69 | int btrfs_insert_fs_root(struct btrfs_fs_info *fs_info, |
70 | struct btrfs_root *root); | 70 | struct btrfs_root *root); |
71 | struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, | 71 | |
72 | struct btrfs_key *location); | 72 | struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info, |
73 | struct btrfs_key *key, | ||
74 | bool check_ref); | ||
75 | static inline struct btrfs_root * | ||
76 | btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, | ||
77 | struct btrfs_key *location) | ||
78 | { | ||
79 | return btrfs_get_fs_root(fs_info, location, true); | ||
80 | } | ||
81 | |||
73 | int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info); | 82 | int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info); |
74 | void btrfs_btree_balance_dirty(struct btrfs_root *root); | 83 | void btrfs_btree_balance_dirty(struct btrfs_root *root); |
75 | void btrfs_btree_balance_dirty_nodelay(struct btrfs_root *root); | 84 | void btrfs_btree_balance_dirty_nodelay(struct btrfs_root *root); |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index c09a40db53db..51731b76900d 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; |
@@ -1482,10 +1490,8 @@ static noinline u64 find_delalloc_range(struct extent_io_tree *tree, | |||
1482 | cur_start = state->end + 1; | 1490 | cur_start = state->end + 1; |
1483 | node = rb_next(node); | 1491 | node = rb_next(node); |
1484 | total_bytes += state->end - state->start + 1; | 1492 | total_bytes += state->end - state->start + 1; |
1485 | if (total_bytes >= max_bytes) { | 1493 | if (total_bytes >= max_bytes) |
1486 | *end = *start + max_bytes - 1; | ||
1487 | break; | 1494 | break; |
1488 | } | ||
1489 | if (!node) | 1495 | if (!node) |
1490 | break; | 1496 | break; |
1491 | } | 1497 | } |
@@ -1614,7 +1620,7 @@ again: | |||
1614 | *start = delalloc_start; | 1620 | *start = delalloc_start; |
1615 | *end = delalloc_end; | 1621 | *end = delalloc_end; |
1616 | free_extent_state(cached_state); | 1622 | free_extent_state(cached_state); |
1617 | return found; | 1623 | return 0; |
1618 | } | 1624 | } |
1619 | 1625 | ||
1620 | /* | 1626 | /* |
@@ -1627,10 +1633,9 @@ again: | |||
1627 | 1633 | ||
1628 | /* | 1634 | /* |
1629 | * make sure to limit the number of pages we try to lock down | 1635 | * make sure to limit the number of pages we try to lock down |
1630 | * if we're looping. | ||
1631 | */ | 1636 | */ |
1632 | if (delalloc_end + 1 - delalloc_start > max_bytes && loops) | 1637 | if (delalloc_end + 1 - delalloc_start > max_bytes) |
1633 | delalloc_end = delalloc_start + PAGE_CACHE_SIZE - 1; | 1638 | delalloc_end = delalloc_start + max_bytes - 1; |
1634 | 1639 | ||
1635 | /* step two, lock all the pages after the page that has start */ | 1640 | /* step two, lock all the pages after the page that has start */ |
1636 | ret = lock_delalloc_pages(inode, locked_page, | 1641 | ret = lock_delalloc_pages(inode, locked_page, |
@@ -1641,8 +1646,7 @@ again: | |||
1641 | */ | 1646 | */ |
1642 | free_extent_state(cached_state); | 1647 | free_extent_state(cached_state); |
1643 | if (!loops) { | 1648 | if (!loops) { |
1644 | unsigned long offset = (*start) & (PAGE_CACHE_SIZE - 1); | 1649 | max_bytes = PAGE_CACHE_SIZE; |
1645 | max_bytes = PAGE_CACHE_SIZE - offset; | ||
1646 | loops = 1; | 1650 | loops = 1; |
1647 | goto again; | 1651 | goto again; |
1648 | } else { | 1652 | } else { |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 22ebc13b6c99..51e3afa78354 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -6437,6 +6437,7 @@ noinline int can_nocow_extent(struct inode *inode, u64 offset, u64 *len, | |||
6437 | 6437 | ||
6438 | if (btrfs_extent_readonly(root, disk_bytenr)) | 6438 | if (btrfs_extent_readonly(root, disk_bytenr)) |
6439 | goto out; | 6439 | goto out; |
6440 | btrfs_release_path(path); | ||
6440 | 6441 | ||
6441 | /* | 6442 | /* |
6442 | * look for other files referencing this extent, if we | 6443 | * look for other files referencing this extent, if we |
@@ -7986,7 +7987,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
7986 | 7987 | ||
7987 | 7988 | ||
7988 | /* check for collisions, even if the name isn't there */ | 7989 | /* check for collisions, even if the name isn't there */ |
7989 | ret = btrfs_check_dir_item_collision(root, new_dir->i_ino, | 7990 | ret = btrfs_check_dir_item_collision(dest, new_dir->i_ino, |
7990 | new_dentry->d_name.name, | 7991 | new_dentry->d_name.name, |
7991 | new_dentry->d_name.len); | 7992 | new_dentry->d_name.len); |
7992 | 7993 | ||
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index a5a26320503f..4a355726151e 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -588,7 +588,7 @@ static struct btrfs_root *read_fs_root(struct btrfs_fs_info *fs_info, | |||
588 | else | 588 | else |
589 | key.offset = (u64)-1; | 589 | key.offset = (u64)-1; |
590 | 590 | ||
591 | return btrfs_read_fs_root_no_name(fs_info, &key); | 591 | return btrfs_get_fs_root(fs_info, &key, false); |
592 | } | 592 | } |
593 | 593 | ||
594 | #ifdef BTRFS_COMPAT_EXTENT_TREE_V0 | 594 | #ifdef BTRFS_COMPAT_EXTENT_TREE_V0 |
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 0b1f4ef8db98..ec71ea44d2b4 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c | |||
@@ -299,11 +299,6 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root) | |||
299 | continue; | 299 | continue; |
300 | } | 300 | } |
301 | 301 | ||
302 | if (btrfs_root_refs(&root->root_item) == 0) { | ||
303 | btrfs_add_dead_root(root); | ||
304 | continue; | ||
305 | } | ||
306 | |||
307 | err = btrfs_init_fs_root(root); | 302 | err = btrfs_init_fs_root(root); |
308 | if (err) { | 303 | if (err) { |
309 | btrfs_free_fs_root(root); | 304 | btrfs_free_fs_root(root); |
@@ -318,6 +313,9 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root) | |||
318 | btrfs_free_fs_root(root); | 313 | btrfs_free_fs_root(root); |
319 | break; | 314 | break; |
320 | } | 315 | } |
316 | |||
317 | if (btrfs_root_refs(&root->root_item) == 0) | ||
318 | btrfs_add_dead_root(root); | ||
321 | } | 319 | } |
322 | 320 | ||
323 | btrfs_free_path(path); | 321 | btrfs_free_path(path); |
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/buffer.c b/fs/buffer.c index 4d7433534f5c..6024877335ca 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -1005,9 +1005,19 @@ grow_dev_page(struct block_device *bdev, sector_t block, | |||
1005 | struct buffer_head *bh; | 1005 | struct buffer_head *bh; |
1006 | sector_t end_block; | 1006 | sector_t end_block; |
1007 | int ret = 0; /* Will call free_more_memory() */ | 1007 | int ret = 0; /* Will call free_more_memory() */ |
1008 | gfp_t gfp_mask; | ||
1008 | 1009 | ||
1009 | page = find_or_create_page(inode->i_mapping, index, | 1010 | gfp_mask = mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS; |
1010 | (mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS)|__GFP_MOVABLE); | 1011 | gfp_mask |= __GFP_MOVABLE; |
1012 | /* | ||
1013 | * XXX: __getblk_slow() can not really deal with failure and | ||
1014 | * will endlessly loop on improvised global reclaim. Prefer | ||
1015 | * looping in the allocator rather than here, at least that | ||
1016 | * code knows what it's doing. | ||
1017 | */ | ||
1018 | gfp_mask |= __GFP_NOFAIL; | ||
1019 | |||
1020 | page = find_or_create_page(inode->i_mapping, index, gfp_mask); | ||
1011 | if (!page) | 1021 | if (!page) |
1012 | return ret; | 1022 | return ret; |
1013 | 1023 | ||
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index a16b4e58bcc6..77fc5e181077 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -120,14 +120,16 @@ cifs_read_super(struct super_block *sb) | |||
120 | { | 120 | { |
121 | struct inode *inode; | 121 | struct inode *inode; |
122 | struct cifs_sb_info *cifs_sb; | 122 | struct cifs_sb_info *cifs_sb; |
123 | struct cifs_tcon *tcon; | ||
123 | int rc = 0; | 124 | int rc = 0; |
124 | 125 | ||
125 | cifs_sb = CIFS_SB(sb); | 126 | cifs_sb = CIFS_SB(sb); |
127 | tcon = cifs_sb_master_tcon(cifs_sb); | ||
126 | 128 | ||
127 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL) | 129 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL) |
128 | sb->s_flags |= MS_POSIXACL; | 130 | sb->s_flags |= MS_POSIXACL; |
129 | 131 | ||
130 | if (cifs_sb_master_tcon(cifs_sb)->ses->capabilities & CAP_LARGE_FILES) | 132 | if (tcon->ses->capabilities & tcon->ses->server->vals->cap_large_files) |
131 | sb->s_maxbytes = MAX_LFS_FILESIZE; | 133 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
132 | else | 134 | else |
133 | sb->s_maxbytes = MAX_NON_LFS; | 135 | sb->s_maxbytes = MAX_NON_LFS; |
@@ -147,7 +149,7 @@ cifs_read_super(struct super_block *sb) | |||
147 | goto out_no_root; | 149 | goto out_no_root; |
148 | } | 150 | } |
149 | 151 | ||
150 | if (cifs_sb_master_tcon(cifs_sb)->nocase) | 152 | if (tcon->nocase) |
151 | sb->s_d_op = &cifs_ci_dentry_ops; | 153 | sb->s_d_op = &cifs_ci_dentry_ops; |
152 | else | 154 | else |
153 | sb->s_d_op = &cifs_dentry_ops; | 155 | sb->s_d_op = &cifs_dentry_ops; |
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..08f9dfb1a894 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -1491,15 +1491,30 @@ struct file_notify_information { | |||
1491 | __u8 FileName[0]; | 1491 | __u8 FileName[0]; |
1492 | } __attribute__((packed)); | 1492 | } __attribute__((packed)); |
1493 | 1493 | ||
1494 | struct reparse_data { | 1494 | /* For IO_REPARSE_TAG_SYMLINK */ |
1495 | __u32 ReparseTag; | 1495 | struct reparse_symlink_data { |
1496 | __u16 ReparseDataLength; | 1496 | __le32 ReparseTag; |
1497 | __le16 ReparseDataLength; | ||
1497 | __u16 Reserved; | 1498 | __u16 Reserved; |
1498 | __u16 SubstituteNameOffset; | 1499 | __le16 SubstituteNameOffset; |
1499 | __u16 SubstituteNameLength; | 1500 | __le16 SubstituteNameLength; |
1500 | __u16 PrintNameOffset; | 1501 | __le16 PrintNameOffset; |
1501 | __u16 PrintNameLength; | 1502 | __le16 PrintNameLength; |
1502 | __u32 Flags; | 1503 | __le32 Flags; |
1504 | char PathBuffer[0]; | ||
1505 | } __attribute__((packed)); | ||
1506 | |||
1507 | /* For IO_REPARSE_TAG_NFS */ | ||
1508 | #define NFS_SPECFILE_LNK 0x00000000014B4E4C | ||
1509 | #define NFS_SPECFILE_CHR 0x0000000000524843 | ||
1510 | #define NFS_SPECFILE_BLK 0x00000000004B4C42 | ||
1511 | #define NFS_SPECFILE_FIFO 0x000000004F464946 | ||
1512 | #define NFS_SPECFILE_SOCK 0x000000004B434F53 | ||
1513 | struct reparse_posix_data { | ||
1514 | __le32 ReparseTag; | ||
1515 | __le16 ReparseDataLength; | ||
1516 | __u16 Reserved; | ||
1517 | __le64 InodeType; /* LNK, FIFO, CHR etc. */ | ||
1503 | char PathBuffer[0]; | 1518 | char PathBuffer[0]; |
1504 | } __attribute__((packed)); | 1519 | } __attribute__((packed)); |
1505 | 1520 | ||
@@ -2652,26 +2667,7 @@ typedef struct file_xattr_info { | |||
2652 | } __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute info | 2667 | } __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute info |
2653 | level 0x205 */ | 2668 | level 0x205 */ |
2654 | 2669 | ||
2655 | 2670 | /* 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 | 2671 | ||
2676 | typedef struct file_chattr_info { | 2672 | typedef struct file_chattr_info { |
2677 | __le64 mask; /* list of all possible attribute bits */ | 2673 | __le64 mask; /* list of all possible attribute bits */ |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index a3d74fea1623..ccd31ab815d4 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) { |
@@ -3089,7 +3088,8 @@ CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon, | |||
3089 | bool is_unicode; | 3088 | bool is_unicode; |
3090 | unsigned int sub_len; | 3089 | unsigned int sub_len; |
3091 | char *sub_start; | 3090 | char *sub_start; |
3092 | struct reparse_data *reparse_buf; | 3091 | struct reparse_symlink_data *reparse_buf; |
3092 | struct reparse_posix_data *posix_buf; | ||
3093 | __u32 data_offset, data_count; | 3093 | __u32 data_offset, data_count; |
3094 | char *end_of_smb; | 3094 | char *end_of_smb; |
3095 | 3095 | ||
@@ -3138,20 +3138,47 @@ CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon, | |||
3138 | goto qreparse_out; | 3138 | goto qreparse_out; |
3139 | } | 3139 | } |
3140 | end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount; | 3140 | end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount; |
3141 | reparse_buf = (struct reparse_data *) | 3141 | reparse_buf = (struct reparse_symlink_data *) |
3142 | ((char *)&pSMBr->hdr.Protocol + data_offset); | 3142 | ((char *)&pSMBr->hdr.Protocol + data_offset); |
3143 | if ((char *)reparse_buf >= end_of_smb) { | 3143 | if ((char *)reparse_buf >= end_of_smb) { |
3144 | rc = -EIO; | 3144 | rc = -EIO; |
3145 | goto qreparse_out; | 3145 | goto qreparse_out; |
3146 | } | 3146 | } |
3147 | if ((reparse_buf->PathBuffer + reparse_buf->PrintNameOffset + | 3147 | if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) { |
3148 | reparse_buf->PrintNameLength) > end_of_smb) { | 3148 | cifs_dbg(FYI, "NFS style reparse tag\n"); |
3149 | posix_buf = (struct reparse_posix_data *)reparse_buf; | ||
3150 | |||
3151 | if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) { | ||
3152 | cifs_dbg(FYI, "unsupported file type 0x%llx\n", | ||
3153 | le64_to_cpu(posix_buf->InodeType)); | ||
3154 | rc = -EOPNOTSUPP; | ||
3155 | goto qreparse_out; | ||
3156 | } | ||
3157 | is_unicode = true; | ||
3158 | sub_len = le16_to_cpu(reparse_buf->ReparseDataLength); | ||
3159 | if (posix_buf->PathBuffer + sub_len > end_of_smb) { | ||
3160 | cifs_dbg(FYI, "reparse buf beyond SMB\n"); | ||
3161 | rc = -EIO; | ||
3162 | goto qreparse_out; | ||
3163 | } | ||
3164 | *symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer, | ||
3165 | sub_len, is_unicode, nls_codepage); | ||
3166 | goto qreparse_out; | ||
3167 | } else if (reparse_buf->ReparseTag != | ||
3168 | cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) { | ||
3169 | rc = -EOPNOTSUPP; | ||
3170 | goto qreparse_out; | ||
3171 | } | ||
3172 | |||
3173 | /* Reparse tag is NTFS symlink */ | ||
3174 | sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) + | ||
3175 | reparse_buf->PathBuffer; | ||
3176 | sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength); | ||
3177 | if (sub_start + sub_len > end_of_smb) { | ||
3149 | cifs_dbg(FYI, "reparse buf beyond SMB\n"); | 3178 | cifs_dbg(FYI, "reparse buf beyond SMB\n"); |
3150 | rc = -EIO; | 3179 | rc = -EIO; |
3151 | goto qreparse_out; | 3180 | goto qreparse_out; |
3152 | } | 3181 | } |
3153 | sub_start = reparse_buf->SubstituteNameOffset + reparse_buf->PathBuffer; | ||
3154 | sub_len = reparse_buf->SubstituteNameLength; | ||
3155 | if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) | 3182 | if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) |
3156 | is_unicode = true; | 3183 | is_unicode = true; |
3157 | else | 3184 | else |
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/netmisc.c b/fs/cifs/netmisc.c index af847e1cf1c1..651a5279607b 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
@@ -780,7 +780,9 @@ static const struct { | |||
780 | ERRDOS, ERRnoaccess, 0xc0000290}, { | 780 | ERRDOS, ERRnoaccess, 0xc0000290}, { |
781 | ERRDOS, ERRbadfunc, 0xc000029c}, { | 781 | ERRDOS, ERRbadfunc, 0xc000029c}, { |
782 | ERRDOS, ERRsymlink, NT_STATUS_STOPPED_ON_SYMLINK}, { | 782 | ERRDOS, ERRsymlink, NT_STATUS_STOPPED_ON_SYMLINK}, { |
783 | ERRDOS, ERRinvlevel, 0x007c0001}, }; | 783 | ERRDOS, ERRinvlevel, 0x007c0001}, { |
784 | 0, 0, 0 } | ||
785 | }; | ||
784 | 786 | ||
785 | /***************************************************************************** | 787 | /***************************************************************************** |
786 | Print an error message from the status code | 788 | Print an error message from the status code |
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..e87387dbf39f 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 | ||
@@ -582,9 +500,9 @@ select_sectype(struct TCP_Server_Info *server, enum securityEnum requested) | |||
582 | return NTLMv2; | 500 | return NTLMv2; |
583 | if (global_secflags & CIFSSEC_MAY_NTLM) | 501 | if (global_secflags & CIFSSEC_MAY_NTLM) |
584 | return NTLM; | 502 | return NTLM; |
585 | /* Fallthrough */ | ||
586 | default: | 503 | default: |
587 | return Unspecified; | 504 | /* Fallthrough to attempt LANMAN authentication next */ |
505 | break; | ||
588 | } | 506 | } |
589 | case CIFS_NEGFLAVOR_LANMAN: | 507 | case CIFS_NEGFLAVOR_LANMAN: |
590 | switch (requested) { | 508 | switch (requested) { |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index eba0efde66d7..edccb5252462 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
@@ -687,6 +687,10 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses) | |||
687 | else | 687 | else |
688 | return -EIO; | 688 | return -EIO; |
689 | 689 | ||
690 | /* no need to send SMB logoff if uid already closed due to reconnect */ | ||
691 | if (ses->need_reconnect) | ||
692 | goto smb2_session_already_dead; | ||
693 | |||
690 | rc = small_smb2_init(SMB2_LOGOFF, NULL, (void **) &req); | 694 | rc = small_smb2_init(SMB2_LOGOFF, NULL, (void **) &req); |
691 | if (rc) | 695 | if (rc) |
692 | return rc; | 696 | return rc; |
@@ -701,6 +705,8 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses) | |||
701 | * No tcon so can't do | 705 | * No tcon so can't do |
702 | * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]); | 706 | * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]); |
703 | */ | 707 | */ |
708 | |||
709 | smb2_session_already_dead: | ||
704 | return rc; | 710 | return rc; |
705 | } | 711 | } |
706 | 712 | ||
diff --git a/fs/cifs/smbfsctl.h b/fs/cifs/smbfsctl.h index d952ee48f4dc..a4b2391fe66e 100644 --- a/fs/cifs/smbfsctl.h +++ b/fs/cifs/smbfsctl.h | |||
@@ -97,9 +97,23 @@ | |||
97 | #define FSCTL_QUERY_NETWORK_INTERFACE_INFO 0x001401FC /* BB add struct */ | 97 | #define FSCTL_QUERY_NETWORK_INTERFACE_INFO 0x001401FC /* BB add struct */ |
98 | #define FSCTL_SRV_READ_HASH 0x001441BB /* BB add struct */ | 98 | #define FSCTL_SRV_READ_HASH 0x001441BB /* BB add struct */ |
99 | 99 | ||
100 | /* See FSCC 2.1.2.5 */ | ||
100 | #define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003 | 101 | #define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003 |
101 | #define IO_REPARSE_TAG_HSM 0xC0000004 | 102 | #define IO_REPARSE_TAG_HSM 0xC0000004 |
102 | #define IO_REPARSE_TAG_SIS 0x80000007 | 103 | #define IO_REPARSE_TAG_SIS 0x80000007 |
104 | #define IO_REPARSE_TAG_HSM2 0x80000006 | ||
105 | #define IO_REPARSE_TAG_DRIVER_EXTENDER 0x80000005 | ||
106 | /* Used by the DFS filter. See MS-DFSC */ | ||
107 | #define IO_REPARSE_TAG_DFS 0x8000000A | ||
108 | /* Used by the DFS filter See MS-DFSC */ | ||
109 | #define IO_REPARSE_TAG_DFSR 0x80000012 | ||
110 | #define IO_REPARSE_TAG_FILTER_MANAGER 0x8000000B | ||
111 | /* See section MS-FSCC 2.1.2.4 */ | ||
112 | #define IO_REPARSE_TAG_SYMLINK 0xA000000C | ||
113 | #define IO_REPARSE_TAG_DEDUP 0x80000013 | ||
114 | #define IO_REPARSE_APPXSTREAM 0xC0000014 | ||
115 | /* NFS symlinks, Win 8/SMB3 and later */ | ||
116 | #define IO_REPARSE_TAG_NFS 0x80000014 | ||
103 | 117 | ||
104 | /* fsctl flags */ | 118 | /* fsctl flags */ |
105 | /* If Flags is set to this value, the request is an FSCTL not ioctl request */ | 119 | /* If Flags is set to this value, the request is an FSCTL not ioctl request */ |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 6fdcb1b4a106..800b938e4061 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -410,8 +410,13 @@ static int | |||
410 | wait_for_free_request(struct TCP_Server_Info *server, const int timeout, | 410 | wait_for_free_request(struct TCP_Server_Info *server, const int timeout, |
411 | const int optype) | 411 | const int optype) |
412 | { | 412 | { |
413 | return wait_for_free_credits(server, timeout, | 413 | int *val; |
414 | server->ops->get_credits_field(server, optype)); | 414 | |
415 | val = server->ops->get_credits_field(server, optype); | ||
416 | /* Since an echo is already inflight, no need to wait to send another */ | ||
417 | if (*val <= 0 && optype == CIFS_ECHO_OP) | ||
418 | return -EAGAIN; | ||
419 | return wait_for_free_credits(server, timeout, val); | ||
415 | } | 420 | } |
416 | 421 | ||
417 | static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf, | 422 | static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf, |
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 1194b1f0f839..f8cde46de9cd 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c | |||
@@ -1783,7 +1783,7 @@ retry: | |||
1783 | d_tmpfile(dentry, inode); | 1783 | d_tmpfile(dentry, inode); |
1784 | err = ext3_orphan_add(handle, inode); | 1784 | err = ext3_orphan_add(handle, inode); |
1785 | if (err) | 1785 | if (err) |
1786 | goto err_drop_inode; | 1786 | goto err_unlock_inode; |
1787 | mark_inode_dirty(inode); | 1787 | mark_inode_dirty(inode); |
1788 | unlock_new_inode(inode); | 1788 | unlock_new_inode(inode); |
1789 | } | 1789 | } |
@@ -1791,10 +1791,9 @@ retry: | |||
1791 | if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries)) | 1791 | if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries)) |
1792 | goto retry; | 1792 | goto retry; |
1793 | return err; | 1793 | return err; |
1794 | err_drop_inode: | 1794 | err_unlock_inode: |
1795 | ext3_journal_stop(handle); | 1795 | ext3_journal_stop(handle); |
1796 | unlock_new_inode(inode); | 1796 | unlock_new_inode(inode); |
1797 | iput(inode); | ||
1798 | return err; | 1797 | return err; |
1799 | } | 1798 | } |
1800 | 1799 | ||
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 0d424d7ac02b..e274e9c1171f 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -2563,7 +2563,7 @@ retry: | |||
2563 | break; | 2563 | break; |
2564 | } | 2564 | } |
2565 | blk_finish_plug(&plug); | 2565 | blk_finish_plug(&plug); |
2566 | if (!ret && !cycled) { | 2566 | if (!ret && !cycled && wbc->nr_to_write > 0) { |
2567 | cycled = 1; | 2567 | cycled = 1; |
2568 | mpd.last_page = writeback_index - 1; | 2568 | mpd.last_page = writeback_index - 1; |
2569 | mpd.first_page = 0; | 2569 | mpd.first_page = 0; |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 1bec5a5c1e45..5a0408d7b114 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -2319,7 +2319,7 @@ retry: | |||
2319 | d_tmpfile(dentry, inode); | 2319 | d_tmpfile(dentry, inode); |
2320 | err = ext4_orphan_add(handle, inode); | 2320 | err = ext4_orphan_add(handle, inode); |
2321 | if (err) | 2321 | if (err) |
2322 | goto err_drop_inode; | 2322 | goto err_unlock_inode; |
2323 | mark_inode_dirty(inode); | 2323 | mark_inode_dirty(inode); |
2324 | unlock_new_inode(inode); | 2324 | unlock_new_inode(inode); |
2325 | } | 2325 | } |
@@ -2328,10 +2328,9 @@ retry: | |||
2328 | if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) | 2328 | if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries)) |
2329 | goto retry; | 2329 | goto retry; |
2330 | return err; | 2330 | return err; |
2331 | err_drop_inode: | 2331 | err_unlock_inode: |
2332 | ext4_journal_stop(handle); | 2332 | ext4_journal_stop(handle); |
2333 | unlock_new_inode(inode); | 2333 | unlock_new_inode(inode); |
2334 | iput(inode); | ||
2335 | return err; | 2334 | return err; |
2336 | } | 2335 | } |
2337 | 2336 | ||
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index c081e34f717f..03e9bebba198 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
@@ -1350,6 +1350,8 @@ retry: | |||
1350 | s_min_extra_isize) { | 1350 | s_min_extra_isize) { |
1351 | tried_min_extra_isize++; | 1351 | tried_min_extra_isize++; |
1352 | new_extra_isize = s_min_extra_isize; | 1352 | new_extra_isize = s_min_extra_isize; |
1353 | kfree(is); is = NULL; | ||
1354 | kfree(bs); bs = NULL; | ||
1353 | goto retry; | 1355 | goto retry; |
1354 | } | 1356 | } |
1355 | error = -1; | 1357 | error = -1; |
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/proc/inode.c b/fs/proc/inode.c index 9f8ef9b7674d..8eaa1ba793fc 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
@@ -288,10 +288,14 @@ static int proc_reg_mmap(struct file *file, struct vm_area_struct *vma) | |||
288 | static unsigned long proc_reg_get_unmapped_area(struct file *file, unsigned long orig_addr, unsigned long len, unsigned long pgoff, unsigned long flags) | 288 | static unsigned long proc_reg_get_unmapped_area(struct file *file, unsigned long orig_addr, unsigned long len, unsigned long pgoff, unsigned long flags) |
289 | { | 289 | { |
290 | struct proc_dir_entry *pde = PDE(file_inode(file)); | 290 | struct proc_dir_entry *pde = PDE(file_inode(file)); |
291 | int rv = -EIO; | 291 | unsigned long rv = -EIO; |
292 | unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); | 292 | unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long) = NULL; |
293 | if (use_pde(pde)) { | 293 | if (use_pde(pde)) { |
294 | get_unmapped_area = pde->proc_fops->get_unmapped_area; | 294 | #ifdef CONFIG_MMU |
295 | get_unmapped_area = current->mm->get_unmapped_area; | ||
296 | #endif | ||
297 | if (pde->proc_fops->get_unmapped_area) | ||
298 | get_unmapped_area = pde->proc_fops->get_unmapped_area; | ||
295 | if (get_unmapped_area) | 299 | if (get_unmapped_area) |
296 | rv = get_unmapped_area(file, orig_addr, len, pgoff, flags); | 300 | rv = get_unmapped_area(file, orig_addr, len, pgoff, flags); |
297 | unuse_pde(pde); | 301 | unuse_pde(pde); |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 7366e9d63cee..390bdab01c3c 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
@@ -941,6 +941,8 @@ static void pte_to_pagemap_entry(pagemap_entry_t *pme, struct pagemapread *pm, | |||
941 | frame = pte_pfn(pte); | 941 | frame = pte_pfn(pte); |
942 | flags = PM_PRESENT; | 942 | flags = PM_PRESENT; |
943 | page = vm_normal_page(vma, addr, pte); | 943 | page = vm_normal_page(vma, addr, pte); |
944 | if (pte_soft_dirty(pte)) | ||
945 | flags2 |= __PM_SOFT_DIRTY; | ||
944 | } else if (is_swap_pte(pte)) { | 946 | } else if (is_swap_pte(pte)) { |
945 | swp_entry_t entry; | 947 | swp_entry_t entry; |
946 | if (pte_swp_soft_dirty(pte)) | 948 | if (pte_swp_soft_dirty(pte)) |
@@ -960,7 +962,7 @@ static void pte_to_pagemap_entry(pagemap_entry_t *pme, struct pagemapread *pm, | |||
960 | 962 | ||
961 | if (page && !PageAnon(page)) | 963 | if (page && !PageAnon(page)) |
962 | flags |= PM_FILE; | 964 | flags |= PM_FILE; |
963 | if ((vma->vm_flags & VM_SOFTDIRTY) || pte_soft_dirty(pte)) | 965 | if ((vma->vm_flags & VM_SOFTDIRTY)) |
964 | flags2 |= __PM_SOFT_DIRTY; | 966 | flags2 |= __PM_SOFT_DIRTY; |
965 | 967 | ||
966 | *pme = make_pme(PM_PFRAME(frame) | PM_STATUS2(pm->v2, flags2) | flags); | 968 | *pme = make_pme(PM_PFRAME(frame) | PM_STATUS2(pm->v2, flags2) | flags); |
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/statfs.c b/fs/statfs.c index c219e733f553..083dc0ac9140 100644 --- a/fs/statfs.c +++ b/fs/statfs.c | |||
@@ -94,7 +94,7 @@ retry: | |||
94 | 94 | ||
95 | int fd_statfs(int fd, struct kstatfs *st) | 95 | int fd_statfs(int fd, struct kstatfs *st) |
96 | { | 96 | { |
97 | struct fd f = fdget(fd); | 97 | struct fd f = fdget_raw(fd); |
98 | int error = -EBADF; | 98 | int error = -EBADF; |
99 | if (f.file) { | 99 | if (f.file) { |
100 | error = vfs_statfs(&f.file->f_path, st); | 100 | error = vfs_statfs(&f.file->f_path, st); |
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 |