diff options
Diffstat (limited to 'fs')
83 files changed, 1122 insertions, 1277 deletions
@@ -52,7 +52,8 @@ | |||
52 | struct aio_ring { | 52 | struct aio_ring { |
53 | unsigned id; /* kernel internal index number */ | 53 | unsigned id; /* kernel internal index number */ |
54 | unsigned nr; /* number of io_events */ | 54 | unsigned nr; /* number of io_events */ |
55 | unsigned head; | 55 | unsigned head; /* Written to by userland or under ring_lock |
56 | * mutex by aio_read_events_ring(). */ | ||
56 | unsigned tail; | 57 | unsigned tail; |
57 | 58 | ||
58 | unsigned magic; | 59 | unsigned magic; |
@@ -243,6 +244,11 @@ static void aio_free_ring(struct kioctx *ctx) | |||
243 | { | 244 | { |
244 | int i; | 245 | int i; |
245 | 246 | ||
247 | /* Disconnect the kiotx from the ring file. This prevents future | ||
248 | * accesses to the kioctx from page migration. | ||
249 | */ | ||
250 | put_aio_ring_file(ctx); | ||
251 | |||
246 | for (i = 0; i < ctx->nr_pages; i++) { | 252 | for (i = 0; i < ctx->nr_pages; i++) { |
247 | struct page *page; | 253 | struct page *page; |
248 | pr_debug("pid(%d) [%d] page->count=%d\n", current->pid, i, | 254 | pr_debug("pid(%d) [%d] page->count=%d\n", current->pid, i, |
@@ -254,8 +260,6 @@ static void aio_free_ring(struct kioctx *ctx) | |||
254 | put_page(page); | 260 | put_page(page); |
255 | } | 261 | } |
256 | 262 | ||
257 | put_aio_ring_file(ctx); | ||
258 | |||
259 | if (ctx->ring_pages && ctx->ring_pages != ctx->internal_pages) { | 263 | if (ctx->ring_pages && ctx->ring_pages != ctx->internal_pages) { |
260 | kfree(ctx->ring_pages); | 264 | kfree(ctx->ring_pages); |
261 | ctx->ring_pages = NULL; | 265 | ctx->ring_pages = NULL; |
@@ -283,29 +287,38 @@ static int aio_migratepage(struct address_space *mapping, struct page *new, | |||
283 | { | 287 | { |
284 | struct kioctx *ctx; | 288 | struct kioctx *ctx; |
285 | unsigned long flags; | 289 | unsigned long flags; |
290 | pgoff_t idx; | ||
286 | int rc; | 291 | int rc; |
287 | 292 | ||
288 | rc = 0; | 293 | rc = 0; |
289 | 294 | ||
290 | /* Make sure the old page hasn't already been changed */ | 295 | /* mapping->private_lock here protects against the kioctx teardown. */ |
291 | spin_lock(&mapping->private_lock); | 296 | spin_lock(&mapping->private_lock); |
292 | ctx = mapping->private_data; | 297 | ctx = mapping->private_data; |
293 | if (ctx) { | 298 | if (!ctx) { |
294 | pgoff_t idx; | 299 | rc = -EINVAL; |
295 | spin_lock_irqsave(&ctx->completion_lock, flags); | 300 | goto out; |
296 | idx = old->index; | 301 | } |
297 | if (idx < (pgoff_t)ctx->nr_pages) { | 302 | |
298 | if (ctx->ring_pages[idx] != old) | 303 | /* The ring_lock mutex. The prevents aio_read_events() from writing |
299 | rc = -EAGAIN; | 304 | * to the ring's head, and prevents page migration from mucking in |
300 | } else | 305 | * a partially initialized kiotx. |
301 | rc = -EINVAL; | 306 | */ |
302 | spin_unlock_irqrestore(&ctx->completion_lock, flags); | 307 | if (!mutex_trylock(&ctx->ring_lock)) { |
308 | rc = -EAGAIN; | ||
309 | goto out; | ||
310 | } | ||
311 | |||
312 | idx = old->index; | ||
313 | if (idx < (pgoff_t)ctx->nr_pages) { | ||
314 | /* Make sure the old page hasn't already been changed */ | ||
315 | if (ctx->ring_pages[idx] != old) | ||
316 | rc = -EAGAIN; | ||
303 | } else | 317 | } else |
304 | rc = -EINVAL; | 318 | rc = -EINVAL; |
305 | spin_unlock(&mapping->private_lock); | ||
306 | 319 | ||
307 | if (rc != 0) | 320 | if (rc != 0) |
308 | return rc; | 321 | goto out_unlock; |
309 | 322 | ||
310 | /* Writeback must be complete */ | 323 | /* Writeback must be complete */ |
311 | BUG_ON(PageWriteback(old)); | 324 | BUG_ON(PageWriteback(old)); |
@@ -314,38 +327,26 @@ static int aio_migratepage(struct address_space *mapping, struct page *new, | |||
314 | rc = migrate_page_move_mapping(mapping, new, old, NULL, mode, 1); | 327 | rc = migrate_page_move_mapping(mapping, new, old, NULL, mode, 1); |
315 | if (rc != MIGRATEPAGE_SUCCESS) { | 328 | if (rc != MIGRATEPAGE_SUCCESS) { |
316 | put_page(new); | 329 | put_page(new); |
317 | return rc; | 330 | goto out_unlock; |
318 | } | 331 | } |
319 | 332 | ||
320 | /* We can potentially race against kioctx teardown here. Use the | 333 | /* Take completion_lock to prevent other writes to the ring buffer |
321 | * address_space's private data lock to protect the mapping's | 334 | * while the old page is copied to the new. This prevents new |
322 | * private_data. | 335 | * events from being lost. |
323 | */ | 336 | */ |
324 | spin_lock(&mapping->private_lock); | 337 | spin_lock_irqsave(&ctx->completion_lock, flags); |
325 | ctx = mapping->private_data; | 338 | migrate_page_copy(new, old); |
326 | if (ctx) { | 339 | BUG_ON(ctx->ring_pages[idx] != old); |
327 | pgoff_t idx; | 340 | ctx->ring_pages[idx] = new; |
328 | spin_lock_irqsave(&ctx->completion_lock, flags); | 341 | spin_unlock_irqrestore(&ctx->completion_lock, flags); |
329 | migrate_page_copy(new, old); | ||
330 | idx = old->index; | ||
331 | if (idx < (pgoff_t)ctx->nr_pages) { | ||
332 | /* And only do the move if things haven't changed */ | ||
333 | if (ctx->ring_pages[idx] == old) | ||
334 | ctx->ring_pages[idx] = new; | ||
335 | else | ||
336 | rc = -EAGAIN; | ||
337 | } else | ||
338 | rc = -EINVAL; | ||
339 | spin_unlock_irqrestore(&ctx->completion_lock, flags); | ||
340 | } else | ||
341 | rc = -EBUSY; | ||
342 | spin_unlock(&mapping->private_lock); | ||
343 | 342 | ||
344 | if (rc == MIGRATEPAGE_SUCCESS) | 343 | /* The old page is no longer accessible. */ |
345 | put_page(old); | 344 | put_page(old); |
346 | else | ||
347 | put_page(new); | ||
348 | 345 | ||
346 | out_unlock: | ||
347 | mutex_unlock(&ctx->ring_lock); | ||
348 | out: | ||
349 | spin_unlock(&mapping->private_lock); | ||
349 | return rc; | 350 | return rc; |
350 | } | 351 | } |
351 | #endif | 352 | #endif |
@@ -380,7 +381,7 @@ static int aio_setup_ring(struct kioctx *ctx) | |||
380 | file = aio_private_file(ctx, nr_pages); | 381 | file = aio_private_file(ctx, nr_pages); |
381 | if (IS_ERR(file)) { | 382 | if (IS_ERR(file)) { |
382 | ctx->aio_ring_file = NULL; | 383 | ctx->aio_ring_file = NULL; |
383 | return -EAGAIN; | 384 | return -ENOMEM; |
384 | } | 385 | } |
385 | 386 | ||
386 | ctx->aio_ring_file = file; | 387 | ctx->aio_ring_file = file; |
@@ -415,7 +416,7 @@ static int aio_setup_ring(struct kioctx *ctx) | |||
415 | 416 | ||
416 | if (unlikely(i != nr_pages)) { | 417 | if (unlikely(i != nr_pages)) { |
417 | aio_free_ring(ctx); | 418 | aio_free_ring(ctx); |
418 | return -EAGAIN; | 419 | return -ENOMEM; |
419 | } | 420 | } |
420 | 421 | ||
421 | ctx->mmap_size = nr_pages * PAGE_SIZE; | 422 | ctx->mmap_size = nr_pages * PAGE_SIZE; |
@@ -429,7 +430,7 @@ static int aio_setup_ring(struct kioctx *ctx) | |||
429 | if (IS_ERR((void *)ctx->mmap_base)) { | 430 | if (IS_ERR((void *)ctx->mmap_base)) { |
430 | ctx->mmap_size = 0; | 431 | ctx->mmap_size = 0; |
431 | aio_free_ring(ctx); | 432 | aio_free_ring(ctx); |
432 | return -EAGAIN; | 433 | return -ENOMEM; |
433 | } | 434 | } |
434 | 435 | ||
435 | pr_debug("mmap address: 0x%08lx\n", ctx->mmap_base); | 436 | pr_debug("mmap address: 0x%08lx\n", ctx->mmap_base); |
@@ -556,6 +557,10 @@ static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm) | |||
556 | rcu_read_unlock(); | 557 | rcu_read_unlock(); |
557 | spin_unlock(&mm->ioctx_lock); | 558 | spin_unlock(&mm->ioctx_lock); |
558 | 559 | ||
560 | /* While kioctx setup is in progress, | ||
561 | * we are protected from page migration | ||
562 | * changes ring_pages by ->ring_lock. | ||
563 | */ | ||
559 | ring = kmap_atomic(ctx->ring_pages[0]); | 564 | ring = kmap_atomic(ctx->ring_pages[0]); |
560 | ring->id = ctx->id; | 565 | ring->id = ctx->id; |
561 | kunmap_atomic(ring); | 566 | kunmap_atomic(ring); |
@@ -640,24 +645,28 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) | |||
640 | 645 | ||
641 | ctx->max_reqs = nr_events; | 646 | ctx->max_reqs = nr_events; |
642 | 647 | ||
643 | if (percpu_ref_init(&ctx->users, free_ioctx_users)) | ||
644 | goto err; | ||
645 | |||
646 | if (percpu_ref_init(&ctx->reqs, free_ioctx_reqs)) | ||
647 | goto err; | ||
648 | |||
649 | spin_lock_init(&ctx->ctx_lock); | 648 | spin_lock_init(&ctx->ctx_lock); |
650 | spin_lock_init(&ctx->completion_lock); | 649 | spin_lock_init(&ctx->completion_lock); |
651 | mutex_init(&ctx->ring_lock); | 650 | mutex_init(&ctx->ring_lock); |
651 | /* Protect against page migration throughout kiotx setup by keeping | ||
652 | * the ring_lock mutex held until setup is complete. */ | ||
653 | mutex_lock(&ctx->ring_lock); | ||
652 | init_waitqueue_head(&ctx->wait); | 654 | init_waitqueue_head(&ctx->wait); |
653 | 655 | ||
654 | INIT_LIST_HEAD(&ctx->active_reqs); | 656 | INIT_LIST_HEAD(&ctx->active_reqs); |
655 | 657 | ||
658 | if (percpu_ref_init(&ctx->users, free_ioctx_users)) | ||
659 | goto err; | ||
660 | |||
661 | if (percpu_ref_init(&ctx->reqs, free_ioctx_reqs)) | ||
662 | goto err; | ||
663 | |||
656 | ctx->cpu = alloc_percpu(struct kioctx_cpu); | 664 | ctx->cpu = alloc_percpu(struct kioctx_cpu); |
657 | if (!ctx->cpu) | 665 | if (!ctx->cpu) |
658 | goto err; | 666 | goto err; |
659 | 667 | ||
660 | if (aio_setup_ring(ctx) < 0) | 668 | err = aio_setup_ring(ctx); |
669 | if (err < 0) | ||
661 | goto err; | 670 | goto err; |
662 | 671 | ||
663 | atomic_set(&ctx->reqs_available, ctx->nr_events - 1); | 672 | atomic_set(&ctx->reqs_available, ctx->nr_events - 1); |
@@ -683,6 +692,9 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) | |||
683 | if (err) | 692 | if (err) |
684 | goto err_cleanup; | 693 | goto err_cleanup; |
685 | 694 | ||
695 | /* Release the ring_lock mutex now that all setup is complete. */ | ||
696 | mutex_unlock(&ctx->ring_lock); | ||
697 | |||
686 | pr_debug("allocated ioctx %p[%ld]: mm=%p mask=0x%x\n", | 698 | pr_debug("allocated ioctx %p[%ld]: mm=%p mask=0x%x\n", |
687 | ctx, ctx->user_id, mm, ctx->nr_events); | 699 | ctx, ctx->user_id, mm, ctx->nr_events); |
688 | return ctx; | 700 | return ctx; |
@@ -692,6 +704,7 @@ err_cleanup: | |||
692 | err_ctx: | 704 | err_ctx: |
693 | aio_free_ring(ctx); | 705 | aio_free_ring(ctx); |
694 | err: | 706 | err: |
707 | mutex_unlock(&ctx->ring_lock); | ||
695 | free_percpu(ctx->cpu); | 708 | free_percpu(ctx->cpu); |
696 | free_percpu(ctx->reqs.pcpu_count); | 709 | free_percpu(ctx->reqs.pcpu_count); |
697 | free_percpu(ctx->users.pcpu_count); | 710 | free_percpu(ctx->users.pcpu_count); |
@@ -1024,6 +1037,7 @@ static long aio_read_events_ring(struct kioctx *ctx, | |||
1024 | 1037 | ||
1025 | mutex_lock(&ctx->ring_lock); | 1038 | mutex_lock(&ctx->ring_lock); |
1026 | 1039 | ||
1040 | /* Access to ->ring_pages here is protected by ctx->ring_lock. */ | ||
1027 | ring = kmap_atomic(ctx->ring_pages[0]); | 1041 | ring = kmap_atomic(ctx->ring_pages[0]); |
1028 | head = ring->head; | 1042 | head = ring->head; |
1029 | tail = ring->tail; | 1043 | tail = ring->tail; |
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c index 3182c0e68b42..232e03d4780d 100644 --- a/fs/autofs4/dev-ioctl.c +++ b/fs/autofs4/dev-ioctl.c | |||
@@ -103,6 +103,9 @@ static struct autofs_dev_ioctl *copy_dev_ioctl(struct autofs_dev_ioctl __user *i | |||
103 | if (tmp.size < sizeof(tmp)) | 103 | if (tmp.size < sizeof(tmp)) |
104 | return ERR_PTR(-EINVAL); | 104 | return ERR_PTR(-EINVAL); |
105 | 105 | ||
106 | if (tmp.size > (PATH_MAX + sizeof(tmp))) | ||
107 | return ERR_PTR(-ENAMETOOLONG); | ||
108 | |||
106 | return memdup_user(in, tmp.size); | 109 | return memdup_user(in, tmp.size); |
107 | } | 110 | } |
108 | 111 | ||
diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index 29696b78d1f4..1c2ce0c87711 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c | |||
@@ -182,6 +182,9 @@ static int bdev_integrity_enabled(struct block_device *bdev, int rw) | |||
182 | */ | 182 | */ |
183 | int bio_integrity_enabled(struct bio *bio) | 183 | int bio_integrity_enabled(struct bio *bio) |
184 | { | 184 | { |
185 | if (!bio_is_rw(bio)) | ||
186 | return 0; | ||
187 | |||
185 | /* Already protected? */ | 188 | /* Already protected? */ |
186 | if (bio_integrity(bio)) | 189 | if (bio_integrity(bio)) |
187 | return 0; | 190 | return 0; |
@@ -309,10 +312,9 @@ static int bio_integrity_generate_verify(struct bio *bio, int operate) | |||
309 | { | 312 | { |
310 | struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); | 313 | struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); |
311 | struct blk_integrity_exchg bix; | 314 | struct blk_integrity_exchg bix; |
312 | struct bio_vec bv; | 315 | struct bio_vec *bv; |
313 | struct bvec_iter iter; | ||
314 | sector_t sector; | 316 | sector_t sector; |
315 | unsigned int sectors, ret = 0; | 317 | unsigned int sectors, ret = 0, i; |
316 | void *prot_buf = bio->bi_integrity->bip_buf; | 318 | void *prot_buf = bio->bi_integrity->bip_buf; |
317 | 319 | ||
318 | if (operate) | 320 | if (operate) |
@@ -323,16 +325,16 @@ static int bio_integrity_generate_verify(struct bio *bio, int operate) | |||
323 | bix.disk_name = bio->bi_bdev->bd_disk->disk_name; | 325 | bix.disk_name = bio->bi_bdev->bd_disk->disk_name; |
324 | bix.sector_size = bi->sector_size; | 326 | bix.sector_size = bi->sector_size; |
325 | 327 | ||
326 | bio_for_each_segment(bv, bio, iter) { | 328 | bio_for_each_segment_all(bv, bio, i) { |
327 | void *kaddr = kmap_atomic(bv.bv_page); | 329 | void *kaddr = kmap_atomic(bv->bv_page); |
328 | bix.data_buf = kaddr + bv.bv_offset; | 330 | bix.data_buf = kaddr + bv->bv_offset; |
329 | bix.data_size = bv.bv_len; | 331 | bix.data_size = bv->bv_len; |
330 | bix.prot_buf = prot_buf; | 332 | bix.prot_buf = prot_buf; |
331 | bix.sector = sector; | 333 | bix.sector = sector; |
332 | 334 | ||
333 | if (operate) { | 335 | if (operate) |
334 | bi->generate_fn(&bix); | 336 | bi->generate_fn(&bix); |
335 | } else { | 337 | else { |
336 | ret = bi->verify_fn(&bix); | 338 | ret = bi->verify_fn(&bix); |
337 | if (ret) { | 339 | if (ret) { |
338 | kunmap_atomic(kaddr); | 340 | kunmap_atomic(kaddr); |
@@ -340,7 +342,7 @@ static int bio_integrity_generate_verify(struct bio *bio, int operate) | |||
340 | } | 342 | } |
341 | } | 343 | } |
342 | 344 | ||
343 | sectors = bv.bv_len / bi->sector_size; | 345 | sectors = bv->bv_len / bi->sector_size; |
344 | sector += sectors; | 346 | sector += sectors; |
345 | prot_buf += sectors * bi->tuple_size; | 347 | prot_buf += sectors * bi->tuple_size; |
346 | 348 | ||
@@ -1002,7 +1002,7 @@ struct bio_map_data { | |||
1002 | }; | 1002 | }; |
1003 | 1003 | ||
1004 | static void bio_set_map_data(struct bio_map_data *bmd, struct bio *bio, | 1004 | static void bio_set_map_data(struct bio_map_data *bmd, struct bio *bio, |
1005 | struct sg_iovec *iov, int iov_count, | 1005 | const struct sg_iovec *iov, int iov_count, |
1006 | int is_our_pages) | 1006 | int is_our_pages) |
1007 | { | 1007 | { |
1008 | memcpy(bmd->sgvecs, iov, sizeof(struct sg_iovec) * iov_count); | 1008 | memcpy(bmd->sgvecs, iov, sizeof(struct sg_iovec) * iov_count); |
@@ -1022,7 +1022,7 @@ static struct bio_map_data *bio_alloc_map_data(int nr_segs, | |||
1022 | sizeof(struct sg_iovec) * iov_count, gfp_mask); | 1022 | sizeof(struct sg_iovec) * iov_count, gfp_mask); |
1023 | } | 1023 | } |
1024 | 1024 | ||
1025 | static int __bio_copy_iov(struct bio *bio, struct sg_iovec *iov, int iov_count, | 1025 | static int __bio_copy_iov(struct bio *bio, const struct sg_iovec *iov, int iov_count, |
1026 | int to_user, int from_user, int do_free_page) | 1026 | int to_user, int from_user, int do_free_page) |
1027 | { | 1027 | { |
1028 | int ret = 0, i; | 1028 | int ret = 0, i; |
@@ -1120,7 +1120,7 @@ EXPORT_SYMBOL(bio_uncopy_user); | |||
1120 | */ | 1120 | */ |
1121 | struct bio *bio_copy_user_iov(struct request_queue *q, | 1121 | struct bio *bio_copy_user_iov(struct request_queue *q, |
1122 | struct rq_map_data *map_data, | 1122 | struct rq_map_data *map_data, |
1123 | struct sg_iovec *iov, int iov_count, | 1123 | const struct sg_iovec *iov, int iov_count, |
1124 | int write_to_vm, gfp_t gfp_mask) | 1124 | int write_to_vm, gfp_t gfp_mask) |
1125 | { | 1125 | { |
1126 | struct bio_map_data *bmd; | 1126 | struct bio_map_data *bmd; |
@@ -1259,7 +1259,7 @@ EXPORT_SYMBOL(bio_copy_user); | |||
1259 | 1259 | ||
1260 | static struct bio *__bio_map_user_iov(struct request_queue *q, | 1260 | static struct bio *__bio_map_user_iov(struct request_queue *q, |
1261 | struct block_device *bdev, | 1261 | struct block_device *bdev, |
1262 | struct sg_iovec *iov, int iov_count, | 1262 | const struct sg_iovec *iov, int iov_count, |
1263 | int write_to_vm, gfp_t gfp_mask) | 1263 | int write_to_vm, gfp_t gfp_mask) |
1264 | { | 1264 | { |
1265 | int i, j; | 1265 | int i, j; |
@@ -1407,7 +1407,7 @@ EXPORT_SYMBOL(bio_map_user); | |||
1407 | * device. Returns an error pointer in case of error. | 1407 | * device. Returns an error pointer in case of error. |
1408 | */ | 1408 | */ |
1409 | struct bio *bio_map_user_iov(struct request_queue *q, struct block_device *bdev, | 1409 | struct bio *bio_map_user_iov(struct request_queue *q, struct block_device *bdev, |
1410 | struct sg_iovec *iov, int iov_count, | 1410 | const struct sg_iovec *iov, int iov_count, |
1411 | int write_to_vm, gfp_t gfp_mask) | 1411 | int write_to_vm, gfp_t gfp_mask) |
1412 | { | 1412 | { |
1413 | struct bio *bio; | 1413 | struct bio *bio; |
diff --git a/fs/block_dev.c b/fs/block_dev.c index ba0d2b05bb78..552a8d13bc32 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -1518,7 +1518,7 @@ ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
1518 | BUG_ON(iocb->ki_pos != pos); | 1518 | BUG_ON(iocb->ki_pos != pos); |
1519 | 1519 | ||
1520 | blk_start_plug(&plug); | 1520 | blk_start_plug(&plug); |
1521 | ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); | 1521 | ret = __generic_file_aio_write(iocb, iov, nr_segs); |
1522 | if (ret > 0) { | 1522 | if (ret > 0) { |
1523 | ssize_t err; | 1523 | ssize_t err; |
1524 | 1524 | ||
diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c index ecb5832c0967..5a201d81049c 100644 --- a/fs/btrfs/async-thread.c +++ b/fs/btrfs/async-thread.c | |||
@@ -323,6 +323,8 @@ void btrfs_destroy_workqueue(struct btrfs_workqueue *wq) | |||
323 | 323 | ||
324 | void btrfs_workqueue_set_max(struct btrfs_workqueue *wq, int max) | 324 | void btrfs_workqueue_set_max(struct btrfs_workqueue *wq, int max) |
325 | { | 325 | { |
326 | if (!wq) | ||
327 | return; | ||
326 | wq->normal->max_active = max; | 328 | wq->normal->max_active = max; |
327 | if (wq->high) | 329 | if (wq->high) |
328 | wq->high->max_active = max; | 330 | wq->high->max_active = max; |
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index aad7201ad11b..10db21fa0926 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
@@ -330,7 +330,10 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, | |||
330 | goto out; | 330 | goto out; |
331 | } | 331 | } |
332 | 332 | ||
333 | root_level = btrfs_old_root_level(root, time_seq); | 333 | if (path->search_commit_root) |
334 | root_level = btrfs_header_level(root->commit_root); | ||
335 | else | ||
336 | root_level = btrfs_old_root_level(root, time_seq); | ||
334 | 337 | ||
335 | if (root_level + 1 == level) { | 338 | if (root_level + 1 == level) { |
336 | srcu_read_unlock(&fs_info->subvol_srcu, index); | 339 | srcu_read_unlock(&fs_info->subvol_srcu, index); |
@@ -1099,9 +1102,9 @@ static int btrfs_find_all_leafs(struct btrfs_trans_handle *trans, | |||
1099 | * | 1102 | * |
1100 | * returns 0 on success, < 0 on error. | 1103 | * returns 0 on success, < 0 on error. |
1101 | */ | 1104 | */ |
1102 | int btrfs_find_all_roots(struct btrfs_trans_handle *trans, | 1105 | static int __btrfs_find_all_roots(struct btrfs_trans_handle *trans, |
1103 | struct btrfs_fs_info *fs_info, u64 bytenr, | 1106 | struct btrfs_fs_info *fs_info, u64 bytenr, |
1104 | u64 time_seq, struct ulist **roots) | 1107 | u64 time_seq, struct ulist **roots) |
1105 | { | 1108 | { |
1106 | struct ulist *tmp; | 1109 | struct ulist *tmp; |
1107 | struct ulist_node *node = NULL; | 1110 | struct ulist_node *node = NULL; |
@@ -1137,6 +1140,20 @@ int btrfs_find_all_roots(struct btrfs_trans_handle *trans, | |||
1137 | return 0; | 1140 | return 0; |
1138 | } | 1141 | } |
1139 | 1142 | ||
1143 | int btrfs_find_all_roots(struct btrfs_trans_handle *trans, | ||
1144 | struct btrfs_fs_info *fs_info, u64 bytenr, | ||
1145 | u64 time_seq, struct ulist **roots) | ||
1146 | { | ||
1147 | int ret; | ||
1148 | |||
1149 | if (!trans) | ||
1150 | down_read(&fs_info->commit_root_sem); | ||
1151 | ret = __btrfs_find_all_roots(trans, fs_info, bytenr, time_seq, roots); | ||
1152 | if (!trans) | ||
1153 | up_read(&fs_info->commit_root_sem); | ||
1154 | return ret; | ||
1155 | } | ||
1156 | |||
1140 | /* | 1157 | /* |
1141 | * this makes the path point to (inum INODE_ITEM ioff) | 1158 | * this makes the path point to (inum INODE_ITEM ioff) |
1142 | */ | 1159 | */ |
@@ -1516,6 +1533,8 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info, | |||
1516 | if (IS_ERR(trans)) | 1533 | if (IS_ERR(trans)) |
1517 | return PTR_ERR(trans); | 1534 | return PTR_ERR(trans); |
1518 | btrfs_get_tree_mod_seq(fs_info, &tree_mod_seq_elem); | 1535 | btrfs_get_tree_mod_seq(fs_info, &tree_mod_seq_elem); |
1536 | } else { | ||
1537 | down_read(&fs_info->commit_root_sem); | ||
1519 | } | 1538 | } |
1520 | 1539 | ||
1521 | ret = btrfs_find_all_leafs(trans, fs_info, extent_item_objectid, | 1540 | ret = btrfs_find_all_leafs(trans, fs_info, extent_item_objectid, |
@@ -1526,8 +1545,8 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info, | |||
1526 | 1545 | ||
1527 | ULIST_ITER_INIT(&ref_uiter); | 1546 | ULIST_ITER_INIT(&ref_uiter); |
1528 | while (!ret && (ref_node = ulist_next(refs, &ref_uiter))) { | 1547 | while (!ret && (ref_node = ulist_next(refs, &ref_uiter))) { |
1529 | ret = btrfs_find_all_roots(trans, fs_info, ref_node->val, | 1548 | ret = __btrfs_find_all_roots(trans, fs_info, ref_node->val, |
1530 | tree_mod_seq_elem.seq, &roots); | 1549 | tree_mod_seq_elem.seq, &roots); |
1531 | if (ret) | 1550 | if (ret) |
1532 | break; | 1551 | break; |
1533 | ULIST_ITER_INIT(&root_uiter); | 1552 | ULIST_ITER_INIT(&root_uiter); |
@@ -1549,6 +1568,8 @@ out: | |||
1549 | if (!search_commit_root) { | 1568 | if (!search_commit_root) { |
1550 | btrfs_put_tree_mod_seq(fs_info, &tree_mod_seq_elem); | 1569 | btrfs_put_tree_mod_seq(fs_info, &tree_mod_seq_elem); |
1551 | btrfs_end_transaction(trans, fs_info->extent_root); | 1570 | btrfs_end_transaction(trans, fs_info->extent_root); |
1571 | } else { | ||
1572 | up_read(&fs_info->commit_root_sem); | ||
1552 | } | 1573 | } |
1553 | 1574 | ||
1554 | return ret; | 1575 | return ret; |
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 88d1b1eedc9c..1bcfcdb23cf4 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -2769,9 +2769,13 @@ again: | |||
2769 | * the commit roots are read only | 2769 | * the commit roots are read only |
2770 | * so we always do read locks | 2770 | * so we always do read locks |
2771 | */ | 2771 | */ |
2772 | if (p->need_commit_sem) | ||
2773 | down_read(&root->fs_info->commit_root_sem); | ||
2772 | b = root->commit_root; | 2774 | b = root->commit_root; |
2773 | extent_buffer_get(b); | 2775 | extent_buffer_get(b); |
2774 | level = btrfs_header_level(b); | 2776 | level = btrfs_header_level(b); |
2777 | if (p->need_commit_sem) | ||
2778 | up_read(&root->fs_info->commit_root_sem); | ||
2775 | if (!p->skip_locking) | 2779 | if (!p->skip_locking) |
2776 | btrfs_tree_read_lock(b); | 2780 | btrfs_tree_read_lock(b); |
2777 | } else { | 2781 | } else { |
@@ -5360,7 +5364,6 @@ int btrfs_compare_trees(struct btrfs_root *left_root, | |||
5360 | { | 5364 | { |
5361 | int ret; | 5365 | int ret; |
5362 | int cmp; | 5366 | int cmp; |
5363 | struct btrfs_trans_handle *trans = NULL; | ||
5364 | struct btrfs_path *left_path = NULL; | 5367 | struct btrfs_path *left_path = NULL; |
5365 | struct btrfs_path *right_path = NULL; | 5368 | struct btrfs_path *right_path = NULL; |
5366 | struct btrfs_key left_key; | 5369 | struct btrfs_key left_key; |
@@ -5378,9 +5381,6 @@ int btrfs_compare_trees(struct btrfs_root *left_root, | |||
5378 | u64 right_blockptr; | 5381 | u64 right_blockptr; |
5379 | u64 left_gen; | 5382 | u64 left_gen; |
5380 | u64 right_gen; | 5383 | u64 right_gen; |
5381 | u64 left_start_ctransid; | ||
5382 | u64 right_start_ctransid; | ||
5383 | u64 ctransid; | ||
5384 | 5384 | ||
5385 | left_path = btrfs_alloc_path(); | 5385 | left_path = btrfs_alloc_path(); |
5386 | if (!left_path) { | 5386 | if (!left_path) { |
@@ -5404,21 +5404,6 @@ int btrfs_compare_trees(struct btrfs_root *left_root, | |||
5404 | right_path->search_commit_root = 1; | 5404 | right_path->search_commit_root = 1; |
5405 | right_path->skip_locking = 1; | 5405 | right_path->skip_locking = 1; |
5406 | 5406 | ||
5407 | spin_lock(&left_root->root_item_lock); | ||
5408 | left_start_ctransid = btrfs_root_ctransid(&left_root->root_item); | ||
5409 | spin_unlock(&left_root->root_item_lock); | ||
5410 | |||
5411 | spin_lock(&right_root->root_item_lock); | ||
5412 | right_start_ctransid = btrfs_root_ctransid(&right_root->root_item); | ||
5413 | spin_unlock(&right_root->root_item_lock); | ||
5414 | |||
5415 | trans = btrfs_join_transaction(left_root); | ||
5416 | if (IS_ERR(trans)) { | ||
5417 | ret = PTR_ERR(trans); | ||
5418 | trans = NULL; | ||
5419 | goto out; | ||
5420 | } | ||
5421 | |||
5422 | /* | 5407 | /* |
5423 | * Strategy: Go to the first items of both trees. Then do | 5408 | * Strategy: Go to the first items of both trees. Then do |
5424 | * | 5409 | * |
@@ -5455,6 +5440,7 @@ int btrfs_compare_trees(struct btrfs_root *left_root, | |||
5455 | * the right if possible or go up and right. | 5440 | * the right if possible or go up and right. |
5456 | */ | 5441 | */ |
5457 | 5442 | ||
5443 | down_read(&left_root->fs_info->commit_root_sem); | ||
5458 | left_level = btrfs_header_level(left_root->commit_root); | 5444 | left_level = btrfs_header_level(left_root->commit_root); |
5459 | left_root_level = left_level; | 5445 | left_root_level = left_level; |
5460 | left_path->nodes[left_level] = left_root->commit_root; | 5446 | left_path->nodes[left_level] = left_root->commit_root; |
@@ -5464,6 +5450,7 @@ int btrfs_compare_trees(struct btrfs_root *left_root, | |||
5464 | right_root_level = right_level; | 5450 | right_root_level = right_level; |
5465 | right_path->nodes[right_level] = right_root->commit_root; | 5451 | right_path->nodes[right_level] = right_root->commit_root; |
5466 | extent_buffer_get(right_path->nodes[right_level]); | 5452 | extent_buffer_get(right_path->nodes[right_level]); |
5453 | up_read(&left_root->fs_info->commit_root_sem); | ||
5467 | 5454 | ||
5468 | if (left_level == 0) | 5455 | if (left_level == 0) |
5469 | btrfs_item_key_to_cpu(left_path->nodes[left_level], | 5456 | btrfs_item_key_to_cpu(left_path->nodes[left_level], |
@@ -5482,67 +5469,6 @@ int btrfs_compare_trees(struct btrfs_root *left_root, | |||
5482 | advance_left = advance_right = 0; | 5469 | advance_left = advance_right = 0; |
5483 | 5470 | ||
5484 | while (1) { | 5471 | while (1) { |
5485 | /* | ||
5486 | * We need to make sure the transaction does not get committed | ||
5487 | * while we do anything on commit roots. This means, we need to | ||
5488 | * join and leave transactions for every item that we process. | ||
5489 | */ | ||
5490 | if (trans && btrfs_should_end_transaction(trans, left_root)) { | ||
5491 | btrfs_release_path(left_path); | ||
5492 | btrfs_release_path(right_path); | ||
5493 | |||
5494 | ret = btrfs_end_transaction(trans, left_root); | ||
5495 | trans = NULL; | ||
5496 | if (ret < 0) | ||
5497 | goto out; | ||
5498 | } | ||
5499 | /* now rejoin the transaction */ | ||
5500 | if (!trans) { | ||
5501 | trans = btrfs_join_transaction(left_root); | ||
5502 | if (IS_ERR(trans)) { | ||
5503 | ret = PTR_ERR(trans); | ||
5504 | trans = NULL; | ||
5505 | goto out; | ||
5506 | } | ||
5507 | |||
5508 | spin_lock(&left_root->root_item_lock); | ||
5509 | ctransid = btrfs_root_ctransid(&left_root->root_item); | ||
5510 | spin_unlock(&left_root->root_item_lock); | ||
5511 | if (ctransid != left_start_ctransid) | ||
5512 | left_start_ctransid = 0; | ||
5513 | |||
5514 | spin_lock(&right_root->root_item_lock); | ||
5515 | ctransid = btrfs_root_ctransid(&right_root->root_item); | ||
5516 | spin_unlock(&right_root->root_item_lock); | ||
5517 | if (ctransid != right_start_ctransid) | ||
5518 | right_start_ctransid = 0; | ||
5519 | |||
5520 | if (!left_start_ctransid || !right_start_ctransid) { | ||
5521 | WARN(1, KERN_WARNING | ||
5522 | "BTRFS: btrfs_compare_tree detected " | ||
5523 | "a change in one of the trees while " | ||
5524 | "iterating. This is probably a " | ||
5525 | "bug.\n"); | ||
5526 | ret = -EIO; | ||
5527 | goto out; | ||
5528 | } | ||
5529 | |||
5530 | /* | ||
5531 | * the commit root may have changed, so start again | ||
5532 | * where we stopped | ||
5533 | */ | ||
5534 | left_path->lowest_level = left_level; | ||
5535 | right_path->lowest_level = right_level; | ||
5536 | ret = btrfs_search_slot(NULL, left_root, | ||
5537 | &left_key, left_path, 0, 0); | ||
5538 | if (ret < 0) | ||
5539 | goto out; | ||
5540 | ret = btrfs_search_slot(NULL, right_root, | ||
5541 | &right_key, right_path, 0, 0); | ||
5542 | if (ret < 0) | ||
5543 | goto out; | ||
5544 | } | ||
5545 | |||
5546 | if (advance_left && !left_end_reached) { | 5472 | if (advance_left && !left_end_reached) { |
5547 | ret = tree_advance(left_root, left_path, &left_level, | 5473 | ret = tree_advance(left_root, left_path, &left_level, |
5548 | left_root_level, | 5474 | left_root_level, |
@@ -5672,14 +5598,6 @@ out: | |||
5672 | btrfs_free_path(left_path); | 5598 | btrfs_free_path(left_path); |
5673 | btrfs_free_path(right_path); | 5599 | btrfs_free_path(right_path); |
5674 | kfree(tmp_buf); | 5600 | kfree(tmp_buf); |
5675 | |||
5676 | if (trans) { | ||
5677 | if (!ret) | ||
5678 | ret = btrfs_end_transaction(trans, left_root); | ||
5679 | else | ||
5680 | btrfs_end_transaction(trans, left_root); | ||
5681 | } | ||
5682 | |||
5683 | return ret; | 5601 | return ret; |
5684 | } | 5602 | } |
5685 | 5603 | ||
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index bc96c03dd259..4c48df572bd6 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -609,6 +609,7 @@ struct btrfs_path { | |||
609 | unsigned int skip_locking:1; | 609 | unsigned int skip_locking:1; |
610 | unsigned int leave_spinning:1; | 610 | unsigned int leave_spinning:1; |
611 | unsigned int search_commit_root:1; | 611 | unsigned int search_commit_root:1; |
612 | unsigned int need_commit_sem:1; | ||
612 | }; | 613 | }; |
613 | 614 | ||
614 | /* | 615 | /* |
@@ -986,7 +987,8 @@ struct btrfs_dev_replace_item { | |||
986 | #define BTRFS_BLOCK_GROUP_RAID10 (1ULL << 6) | 987 | #define BTRFS_BLOCK_GROUP_RAID10 (1ULL << 6) |
987 | #define BTRFS_BLOCK_GROUP_RAID5 (1ULL << 7) | 988 | #define BTRFS_BLOCK_GROUP_RAID5 (1ULL << 7) |
988 | #define BTRFS_BLOCK_GROUP_RAID6 (1ULL << 8) | 989 | #define BTRFS_BLOCK_GROUP_RAID6 (1ULL << 8) |
989 | #define BTRFS_BLOCK_GROUP_RESERVED BTRFS_AVAIL_ALLOC_BIT_SINGLE | 990 | #define BTRFS_BLOCK_GROUP_RESERVED (BTRFS_AVAIL_ALLOC_BIT_SINGLE | \ |
991 | BTRFS_SPACE_INFO_GLOBAL_RSV) | ||
990 | 992 | ||
991 | enum btrfs_raid_types { | 993 | enum btrfs_raid_types { |
992 | BTRFS_RAID_RAID10, | 994 | BTRFS_RAID_RAID10, |
@@ -1018,6 +1020,12 @@ enum btrfs_raid_types { | |||
1018 | */ | 1020 | */ |
1019 | #define BTRFS_AVAIL_ALLOC_BIT_SINGLE (1ULL << 48) | 1021 | #define BTRFS_AVAIL_ALLOC_BIT_SINGLE (1ULL << 48) |
1020 | 1022 | ||
1023 | /* | ||
1024 | * A fake block group type that is used to communicate global block reserve | ||
1025 | * size to userspace via the SPACE_INFO ioctl. | ||
1026 | */ | ||
1027 | #define BTRFS_SPACE_INFO_GLOBAL_RSV (1ULL << 49) | ||
1028 | |||
1021 | #define BTRFS_EXTENDED_PROFILE_MASK (BTRFS_BLOCK_GROUP_PROFILE_MASK | \ | 1029 | #define BTRFS_EXTENDED_PROFILE_MASK (BTRFS_BLOCK_GROUP_PROFILE_MASK | \ |
1022 | BTRFS_AVAIL_ALLOC_BIT_SINGLE) | 1030 | BTRFS_AVAIL_ALLOC_BIT_SINGLE) |
1023 | 1031 | ||
@@ -1440,7 +1448,7 @@ struct btrfs_fs_info { | |||
1440 | */ | 1448 | */ |
1441 | struct mutex ordered_extent_flush_mutex; | 1449 | struct mutex ordered_extent_flush_mutex; |
1442 | 1450 | ||
1443 | struct rw_semaphore extent_commit_sem; | 1451 | struct rw_semaphore commit_root_sem; |
1444 | 1452 | ||
1445 | struct rw_semaphore cleanup_work_sem; | 1453 | struct rw_semaphore cleanup_work_sem; |
1446 | 1454 | ||
@@ -1711,7 +1719,6 @@ struct btrfs_root { | |||
1711 | struct btrfs_block_rsv *block_rsv; | 1719 | struct btrfs_block_rsv *block_rsv; |
1712 | 1720 | ||
1713 | /* free ino cache stuff */ | 1721 | /* free ino cache stuff */ |
1714 | struct mutex fs_commit_mutex; | ||
1715 | struct btrfs_free_space_ctl *free_ino_ctl; | 1722 | struct btrfs_free_space_ctl *free_ino_ctl; |
1716 | enum btrfs_caching_type cached; | 1723 | enum btrfs_caching_type cached; |
1717 | spinlock_t cache_lock; | 1724 | spinlock_t cache_lock; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index bd0f752b797b..029d46c2e170 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -329,6 +329,8 @@ static int verify_parent_transid(struct extent_io_tree *io_tree, | |||
329 | { | 329 | { |
330 | struct extent_state *cached_state = NULL; | 330 | struct extent_state *cached_state = NULL; |
331 | int ret; | 331 | int ret; |
332 | bool need_lock = (current->journal_info == | ||
333 | (void *)BTRFS_SEND_TRANS_STUB); | ||
332 | 334 | ||
333 | if (!parent_transid || btrfs_header_generation(eb) == parent_transid) | 335 | if (!parent_transid || btrfs_header_generation(eb) == parent_transid) |
334 | return 0; | 336 | return 0; |
@@ -336,6 +338,11 @@ static int verify_parent_transid(struct extent_io_tree *io_tree, | |||
336 | if (atomic) | 338 | if (atomic) |
337 | return -EAGAIN; | 339 | return -EAGAIN; |
338 | 340 | ||
341 | if (need_lock) { | ||
342 | btrfs_tree_read_lock(eb); | ||
343 | btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); | ||
344 | } | ||
345 | |||
339 | lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1, | 346 | lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1, |
340 | 0, &cached_state); | 347 | 0, &cached_state); |
341 | if (extent_buffer_uptodate(eb) && | 348 | if (extent_buffer_uptodate(eb) && |
@@ -347,10 +354,21 @@ static int verify_parent_transid(struct extent_io_tree *io_tree, | |||
347 | "found %llu\n", | 354 | "found %llu\n", |
348 | eb->start, parent_transid, btrfs_header_generation(eb)); | 355 | eb->start, parent_transid, btrfs_header_generation(eb)); |
349 | ret = 1; | 356 | ret = 1; |
350 | clear_extent_buffer_uptodate(eb); | 357 | |
358 | /* | ||
359 | * Things reading via commit roots that don't have normal protection, | ||
360 | * like send, can have a really old block in cache that may point at a | ||
361 | * block that has been free'd and re-allocated. So don't clear uptodate | ||
362 | * if we find an eb that is under IO (dirty/writeback) because we could | ||
363 | * end up reading in the stale data and then writing it back out and | ||
364 | * making everybody very sad. | ||
365 | */ | ||
366 | if (!extent_buffer_under_io(eb)) | ||
367 | clear_extent_buffer_uptodate(eb); | ||
351 | out: | 368 | out: |
352 | unlock_extent_cached(io_tree, eb->start, eb->start + eb->len - 1, | 369 | unlock_extent_cached(io_tree, eb->start, eb->start + eb->len - 1, |
353 | &cached_state, GFP_NOFS); | 370 | &cached_state, GFP_NOFS); |
371 | btrfs_tree_read_unlock_blocking(eb); | ||
354 | return ret; | 372 | return ret; |
355 | } | 373 | } |
356 | 374 | ||
@@ -1546,7 +1564,6 @@ int btrfs_init_fs_root(struct btrfs_root *root) | |||
1546 | root->subv_writers = writers; | 1564 | root->subv_writers = writers; |
1547 | 1565 | ||
1548 | btrfs_init_free_ino_ctl(root); | 1566 | btrfs_init_free_ino_ctl(root); |
1549 | mutex_init(&root->fs_commit_mutex); | ||
1550 | spin_lock_init(&root->cache_lock); | 1567 | spin_lock_init(&root->cache_lock); |
1551 | init_waitqueue_head(&root->cache_wait); | 1568 | init_waitqueue_head(&root->cache_wait); |
1552 | 1569 | ||
@@ -2324,7 +2341,7 @@ int open_ctree(struct super_block *sb, | |||
2324 | mutex_init(&fs_info->transaction_kthread_mutex); | 2341 | mutex_init(&fs_info->transaction_kthread_mutex); |
2325 | mutex_init(&fs_info->cleaner_mutex); | 2342 | mutex_init(&fs_info->cleaner_mutex); |
2326 | mutex_init(&fs_info->volume_mutex); | 2343 | mutex_init(&fs_info->volume_mutex); |
2327 | init_rwsem(&fs_info->extent_commit_sem); | 2344 | init_rwsem(&fs_info->commit_root_sem); |
2328 | init_rwsem(&fs_info->cleanup_work_sem); | 2345 | init_rwsem(&fs_info->cleanup_work_sem); |
2329 | init_rwsem(&fs_info->subvol_sem); | 2346 | init_rwsem(&fs_info->subvol_sem); |
2330 | sema_init(&fs_info->uuid_tree_rescan_sem, 1); | 2347 | sema_init(&fs_info->uuid_tree_rescan_sem, 1); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index c6b6a6e3e735..1306487c82cf 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -419,7 +419,7 @@ static noinline void caching_thread(struct btrfs_work *work) | |||
419 | again: | 419 | again: |
420 | mutex_lock(&caching_ctl->mutex); | 420 | mutex_lock(&caching_ctl->mutex); |
421 | /* need to make sure the commit_root doesn't disappear */ | 421 | /* need to make sure the commit_root doesn't disappear */ |
422 | down_read(&fs_info->extent_commit_sem); | 422 | down_read(&fs_info->commit_root_sem); |
423 | 423 | ||
424 | next: | 424 | next: |
425 | ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0); | 425 | ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0); |
@@ -443,10 +443,10 @@ next: | |||
443 | break; | 443 | break; |
444 | 444 | ||
445 | if (need_resched() || | 445 | if (need_resched() || |
446 | rwsem_is_contended(&fs_info->extent_commit_sem)) { | 446 | rwsem_is_contended(&fs_info->commit_root_sem)) { |
447 | caching_ctl->progress = last; | 447 | caching_ctl->progress = last; |
448 | btrfs_release_path(path); | 448 | btrfs_release_path(path); |
449 | up_read(&fs_info->extent_commit_sem); | 449 | up_read(&fs_info->commit_root_sem); |
450 | mutex_unlock(&caching_ctl->mutex); | 450 | mutex_unlock(&caching_ctl->mutex); |
451 | cond_resched(); | 451 | cond_resched(); |
452 | goto again; | 452 | goto again; |
@@ -513,7 +513,7 @@ next: | |||
513 | 513 | ||
514 | err: | 514 | err: |
515 | btrfs_free_path(path); | 515 | btrfs_free_path(path); |
516 | up_read(&fs_info->extent_commit_sem); | 516 | up_read(&fs_info->commit_root_sem); |
517 | 517 | ||
518 | free_excluded_extents(extent_root, block_group); | 518 | free_excluded_extents(extent_root, block_group); |
519 | 519 | ||
@@ -633,10 +633,10 @@ static int cache_block_group(struct btrfs_block_group_cache *cache, | |||
633 | return 0; | 633 | return 0; |
634 | } | 634 | } |
635 | 635 | ||
636 | down_write(&fs_info->extent_commit_sem); | 636 | down_write(&fs_info->commit_root_sem); |
637 | atomic_inc(&caching_ctl->count); | 637 | atomic_inc(&caching_ctl->count); |
638 | list_add_tail(&caching_ctl->list, &fs_info->caching_block_groups); | 638 | list_add_tail(&caching_ctl->list, &fs_info->caching_block_groups); |
639 | up_write(&fs_info->extent_commit_sem); | 639 | up_write(&fs_info->commit_root_sem); |
640 | 640 | ||
641 | btrfs_get_block_group(cache); | 641 | btrfs_get_block_group(cache); |
642 | 642 | ||
@@ -2444,7 +2444,8 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, | |||
2444 | spin_unlock(&locked_ref->lock); | 2444 | spin_unlock(&locked_ref->lock); |
2445 | spin_lock(&delayed_refs->lock); | 2445 | spin_lock(&delayed_refs->lock); |
2446 | spin_lock(&locked_ref->lock); | 2446 | spin_lock(&locked_ref->lock); |
2447 | if (rb_first(&locked_ref->ref_root)) { | 2447 | if (rb_first(&locked_ref->ref_root) || |
2448 | locked_ref->extent_op) { | ||
2448 | spin_unlock(&locked_ref->lock); | 2449 | spin_unlock(&locked_ref->lock); |
2449 | spin_unlock(&delayed_refs->lock); | 2450 | spin_unlock(&delayed_refs->lock); |
2450 | continue; | 2451 | continue; |
@@ -5470,7 +5471,7 @@ void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans, | |||
5470 | struct btrfs_block_group_cache *cache; | 5471 | struct btrfs_block_group_cache *cache; |
5471 | struct btrfs_space_info *space_info; | 5472 | struct btrfs_space_info *space_info; |
5472 | 5473 | ||
5473 | down_write(&fs_info->extent_commit_sem); | 5474 | down_write(&fs_info->commit_root_sem); |
5474 | 5475 | ||
5475 | list_for_each_entry_safe(caching_ctl, next, | 5476 | list_for_each_entry_safe(caching_ctl, next, |
5476 | &fs_info->caching_block_groups, list) { | 5477 | &fs_info->caching_block_groups, list) { |
@@ -5489,7 +5490,7 @@ void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans, | |||
5489 | else | 5490 | else |
5490 | fs_info->pinned_extents = &fs_info->freed_extents[0]; | 5491 | fs_info->pinned_extents = &fs_info->freed_extents[0]; |
5491 | 5492 | ||
5492 | up_write(&fs_info->extent_commit_sem); | 5493 | up_write(&fs_info->commit_root_sem); |
5493 | 5494 | ||
5494 | list_for_each_entry_rcu(space_info, &fs_info->space_info, list) | 5495 | list_for_each_entry_rcu(space_info, &fs_info->space_info, list) |
5495 | percpu_counter_set(&space_info->total_bytes_pinned, 0); | 5496 | percpu_counter_set(&space_info->total_bytes_pinned, 0); |
@@ -5744,6 +5745,8 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, | |||
5744 | "unable to find ref byte nr %llu parent %llu root %llu owner %llu offset %llu", | 5745 | "unable to find ref byte nr %llu parent %llu root %llu owner %llu offset %llu", |
5745 | bytenr, parent, root_objectid, owner_objectid, | 5746 | bytenr, parent, root_objectid, owner_objectid, |
5746 | owner_offset); | 5747 | owner_offset); |
5748 | btrfs_abort_transaction(trans, extent_root, ret); | ||
5749 | goto out; | ||
5747 | } else { | 5750 | } else { |
5748 | btrfs_abort_transaction(trans, extent_root, ret); | 5751 | btrfs_abort_transaction(trans, extent_root, ret); |
5749 | goto out; | 5752 | goto out; |
@@ -8255,14 +8258,14 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info) | |||
8255 | struct btrfs_caching_control *caching_ctl; | 8258 | struct btrfs_caching_control *caching_ctl; |
8256 | struct rb_node *n; | 8259 | struct rb_node *n; |
8257 | 8260 | ||
8258 | down_write(&info->extent_commit_sem); | 8261 | down_write(&info->commit_root_sem); |
8259 | while (!list_empty(&info->caching_block_groups)) { | 8262 | while (!list_empty(&info->caching_block_groups)) { |
8260 | caching_ctl = list_entry(info->caching_block_groups.next, | 8263 | caching_ctl = list_entry(info->caching_block_groups.next, |
8261 | struct btrfs_caching_control, list); | 8264 | struct btrfs_caching_control, list); |
8262 | list_del(&caching_ctl->list); | 8265 | list_del(&caching_ctl->list); |
8263 | put_caching_control(caching_ctl); | 8266 | put_caching_control(caching_ctl); |
8264 | } | 8267 | } |
8265 | up_write(&info->extent_commit_sem); | 8268 | up_write(&info->commit_root_sem); |
8266 | 8269 | ||
8267 | spin_lock(&info->block_group_cache_lock); | 8270 | spin_lock(&info->block_group_cache_lock); |
8268 | while ((n = rb_last(&info->block_group_cache_tree)) != NULL) { | 8271 | while ((n = rb_last(&info->block_group_cache_tree)) != NULL) { |
@@ -8336,9 +8339,15 @@ static void __link_block_group(struct btrfs_space_info *space_info, | |||
8336 | struct btrfs_block_group_cache *cache) | 8339 | struct btrfs_block_group_cache *cache) |
8337 | { | 8340 | { |
8338 | int index = get_block_group_index(cache); | 8341 | int index = get_block_group_index(cache); |
8342 | bool first = false; | ||
8339 | 8343 | ||
8340 | down_write(&space_info->groups_sem); | 8344 | down_write(&space_info->groups_sem); |
8341 | if (list_empty(&space_info->block_groups[index])) { | 8345 | if (list_empty(&space_info->block_groups[index])) |
8346 | first = true; | ||
8347 | list_add_tail(&cache->list, &space_info->block_groups[index]); | ||
8348 | up_write(&space_info->groups_sem); | ||
8349 | |||
8350 | if (first) { | ||
8342 | struct kobject *kobj = &space_info->block_group_kobjs[index]; | 8351 | struct kobject *kobj = &space_info->block_group_kobjs[index]; |
8343 | int ret; | 8352 | int ret; |
8344 | 8353 | ||
@@ -8350,8 +8359,6 @@ static void __link_block_group(struct btrfs_space_info *space_info, | |||
8350 | kobject_put(&space_info->kobj); | 8359 | kobject_put(&space_info->kobj); |
8351 | } | 8360 | } |
8352 | } | 8361 | } |
8353 | list_add_tail(&cache->list, &space_info->block_groups[index]); | ||
8354 | up_write(&space_info->groups_sem); | ||
8355 | } | 8362 | } |
8356 | 8363 | ||
8357 | static struct btrfs_block_group_cache * | 8364 | static struct btrfs_block_group_cache * |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index ae69a00387e7..3955e475ceec 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -749,6 +749,7 @@ again: | |||
749 | * our range starts | 749 | * our range starts |
750 | */ | 750 | */ |
751 | node = tree_search(tree, start); | 751 | node = tree_search(tree, start); |
752 | process_node: | ||
752 | if (!node) | 753 | if (!node) |
753 | break; | 754 | break; |
754 | 755 | ||
@@ -769,7 +770,10 @@ again: | |||
769 | if (start > end) | 770 | if (start > end) |
770 | break; | 771 | break; |
771 | 772 | ||
772 | cond_resched_lock(&tree->lock); | 773 | if (!cond_resched_lock(&tree->lock)) { |
774 | node = rb_next(node); | ||
775 | goto process_node; | ||
776 | } | ||
773 | } | 777 | } |
774 | out: | 778 | out: |
775 | spin_unlock(&tree->lock); | 779 | spin_unlock(&tree->lock); |
@@ -4306,7 +4310,7 @@ static void __free_extent_buffer(struct extent_buffer *eb) | |||
4306 | kmem_cache_free(extent_buffer_cache, eb); | 4310 | kmem_cache_free(extent_buffer_cache, eb); |
4307 | } | 4311 | } |
4308 | 4312 | ||
4309 | static int extent_buffer_under_io(struct extent_buffer *eb) | 4313 | int extent_buffer_under_io(struct extent_buffer *eb) |
4310 | { | 4314 | { |
4311 | return (atomic_read(&eb->io_pages) || | 4315 | return (atomic_read(&eb->io_pages) || |
4312 | test_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags) || | 4316 | test_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags) || |
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 58b27e5ab521..c488b45237bf 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h | |||
@@ -320,6 +320,7 @@ int set_extent_buffer_dirty(struct extent_buffer *eb); | |||
320 | int set_extent_buffer_uptodate(struct extent_buffer *eb); | 320 | int set_extent_buffer_uptodate(struct extent_buffer *eb); |
321 | int clear_extent_buffer_uptodate(struct extent_buffer *eb); | 321 | int clear_extent_buffer_uptodate(struct extent_buffer *eb); |
322 | int extent_buffer_uptodate(struct extent_buffer *eb); | 322 | int extent_buffer_uptodate(struct extent_buffer *eb); |
323 | int extent_buffer_under_io(struct extent_buffer *eb); | ||
323 | int map_private_extent_buffer(struct extent_buffer *eb, unsigned long offset, | 324 | int map_private_extent_buffer(struct extent_buffer *eb, unsigned long offset, |
324 | unsigned long min_len, char **map, | 325 | unsigned long min_len, char **map, |
325 | unsigned long *map_start, | 326 | unsigned long *map_start, |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index c660527af838..eb742c07e7a4 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -425,13 +425,8 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages, | |||
425 | struct page *page = prepared_pages[pg]; | 425 | struct page *page = prepared_pages[pg]; |
426 | /* | 426 | /* |
427 | * Copy data from userspace to the current page | 427 | * Copy data from userspace to the current page |
428 | * | ||
429 | * Disable pagefault to avoid recursive lock since | ||
430 | * the pages are already locked | ||
431 | */ | 428 | */ |
432 | pagefault_disable(); | ||
433 | copied = iov_iter_copy_from_user_atomic(page, i, offset, count); | 429 | copied = iov_iter_copy_from_user_atomic(page, i, offset, count); |
434 | pagefault_enable(); | ||
435 | 430 | ||
436 | /* Flush processor's dcache for this page */ | 431 | /* Flush processor's dcache for this page */ |
437 | flush_dcache_page(page); | 432 | flush_dcache_page(page); |
@@ -1665,7 +1660,7 @@ again: | |||
1665 | static ssize_t __btrfs_direct_write(struct kiocb *iocb, | 1660 | static ssize_t __btrfs_direct_write(struct kiocb *iocb, |
1666 | const struct iovec *iov, | 1661 | const struct iovec *iov, |
1667 | unsigned long nr_segs, loff_t pos, | 1662 | unsigned long nr_segs, loff_t pos, |
1668 | loff_t *ppos, size_t count, size_t ocount) | 1663 | size_t count, size_t ocount) |
1669 | { | 1664 | { |
1670 | struct file *file = iocb->ki_filp; | 1665 | struct file *file = iocb->ki_filp; |
1671 | struct iov_iter i; | 1666 | struct iov_iter i; |
@@ -1674,7 +1669,7 @@ static ssize_t __btrfs_direct_write(struct kiocb *iocb, | |||
1674 | loff_t endbyte; | 1669 | loff_t endbyte; |
1675 | int err; | 1670 | int err; |
1676 | 1671 | ||
1677 | written = generic_file_direct_write(iocb, iov, &nr_segs, pos, ppos, | 1672 | written = generic_file_direct_write(iocb, iov, &nr_segs, pos, |
1678 | count, ocount); | 1673 | count, ocount); |
1679 | 1674 | ||
1680 | if (written < 0 || written == count) | 1675 | if (written < 0 || written == count) |
@@ -1693,7 +1688,7 @@ static ssize_t __btrfs_direct_write(struct kiocb *iocb, | |||
1693 | if (err) | 1688 | if (err) |
1694 | goto out; | 1689 | goto out; |
1695 | written += written_buffered; | 1690 | written += written_buffered; |
1696 | *ppos = pos + written_buffered; | 1691 | iocb->ki_pos = pos + written_buffered; |
1697 | invalidate_mapping_pages(file->f_mapping, pos >> PAGE_CACHE_SHIFT, | 1692 | invalidate_mapping_pages(file->f_mapping, pos >> PAGE_CACHE_SHIFT, |
1698 | endbyte >> PAGE_CACHE_SHIFT); | 1693 | endbyte >> PAGE_CACHE_SHIFT); |
1699 | out: | 1694 | out: |
@@ -1725,8 +1720,8 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
1725 | struct file *file = iocb->ki_filp; | 1720 | struct file *file = iocb->ki_filp; |
1726 | struct inode *inode = file_inode(file); | 1721 | struct inode *inode = file_inode(file); |
1727 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1722 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1728 | loff_t *ppos = &iocb->ki_pos; | ||
1729 | u64 start_pos; | 1723 | u64 start_pos; |
1724 | u64 end_pos; | ||
1730 | ssize_t num_written = 0; | 1725 | ssize_t num_written = 0; |
1731 | ssize_t err = 0; | 1726 | ssize_t err = 0; |
1732 | size_t count, ocount; | 1727 | size_t count, ocount; |
@@ -1781,7 +1776,9 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
1781 | 1776 | ||
1782 | start_pos = round_down(pos, root->sectorsize); | 1777 | start_pos = round_down(pos, root->sectorsize); |
1783 | if (start_pos > i_size_read(inode)) { | 1778 | if (start_pos > i_size_read(inode)) { |
1784 | err = btrfs_cont_expand(inode, i_size_read(inode), start_pos); | 1779 | /* Expand hole size to cover write data, preventing empty gap */ |
1780 | end_pos = round_up(pos + iov->iov_len, root->sectorsize); | ||
1781 | err = btrfs_cont_expand(inode, i_size_read(inode), end_pos); | ||
1785 | if (err) { | 1782 | if (err) { |
1786 | mutex_unlock(&inode->i_mutex); | 1783 | mutex_unlock(&inode->i_mutex); |
1787 | goto out; | 1784 | goto out; |
@@ -1793,7 +1790,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
1793 | 1790 | ||
1794 | if (unlikely(file->f_flags & O_DIRECT)) { | 1791 | if (unlikely(file->f_flags & O_DIRECT)) { |
1795 | num_written = __btrfs_direct_write(iocb, iov, nr_segs, | 1792 | num_written = __btrfs_direct_write(iocb, iov, nr_segs, |
1796 | pos, ppos, count, ocount); | 1793 | pos, count, ocount); |
1797 | } else { | 1794 | } else { |
1798 | struct iov_iter i; | 1795 | struct iov_iter i; |
1799 | 1796 | ||
@@ -1801,7 +1798,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
1801 | 1798 | ||
1802 | num_written = __btrfs_buffered_write(file, &i, pos); | 1799 | num_written = __btrfs_buffered_write(file, &i, pos); |
1803 | if (num_written > 0) | 1800 | if (num_written > 0) |
1804 | *ppos = pos + num_written; | 1801 | iocb->ki_pos = pos + num_written; |
1805 | } | 1802 | } |
1806 | 1803 | ||
1807 | mutex_unlock(&inode->i_mutex); | 1804 | mutex_unlock(&inode->i_mutex); |
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c index ab485e57b6fe..cc8ca193d830 100644 --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c | |||
@@ -55,7 +55,7 @@ static int caching_kthread(void *data) | |||
55 | key.type = BTRFS_INODE_ITEM_KEY; | 55 | key.type = BTRFS_INODE_ITEM_KEY; |
56 | again: | 56 | again: |
57 | /* need to make sure the commit_root doesn't disappear */ | 57 | /* need to make sure the commit_root doesn't disappear */ |
58 | mutex_lock(&root->fs_commit_mutex); | 58 | down_read(&fs_info->commit_root_sem); |
59 | 59 | ||
60 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 60 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
61 | if (ret < 0) | 61 | if (ret < 0) |
@@ -88,7 +88,7 @@ again: | |||
88 | btrfs_item_key_to_cpu(leaf, &key, 0); | 88 | btrfs_item_key_to_cpu(leaf, &key, 0); |
89 | btrfs_release_path(path); | 89 | btrfs_release_path(path); |
90 | root->cache_progress = last; | 90 | root->cache_progress = last; |
91 | mutex_unlock(&root->fs_commit_mutex); | 91 | up_read(&fs_info->commit_root_sem); |
92 | schedule_timeout(1); | 92 | schedule_timeout(1); |
93 | goto again; | 93 | goto again; |
94 | } else | 94 | } else |
@@ -127,7 +127,7 @@ next: | |||
127 | btrfs_unpin_free_ino(root); | 127 | btrfs_unpin_free_ino(root); |
128 | out: | 128 | out: |
129 | wake_up(&root->cache_wait); | 129 | wake_up(&root->cache_wait); |
130 | mutex_unlock(&root->fs_commit_mutex); | 130 | up_read(&fs_info->commit_root_sem); |
131 | 131 | ||
132 | btrfs_free_path(path); | 132 | btrfs_free_path(path); |
133 | 133 | ||
@@ -223,11 +223,11 @@ again: | |||
223 | * or the caching work is done. | 223 | * or the caching work is done. |
224 | */ | 224 | */ |
225 | 225 | ||
226 | mutex_lock(&root->fs_commit_mutex); | 226 | down_write(&root->fs_info->commit_root_sem); |
227 | spin_lock(&root->cache_lock); | 227 | spin_lock(&root->cache_lock); |
228 | if (root->cached == BTRFS_CACHE_FINISHED) { | 228 | if (root->cached == BTRFS_CACHE_FINISHED) { |
229 | spin_unlock(&root->cache_lock); | 229 | spin_unlock(&root->cache_lock); |
230 | mutex_unlock(&root->fs_commit_mutex); | 230 | up_write(&root->fs_info->commit_root_sem); |
231 | goto again; | 231 | goto again; |
232 | } | 232 | } |
233 | spin_unlock(&root->cache_lock); | 233 | spin_unlock(&root->cache_lock); |
@@ -240,7 +240,7 @@ again: | |||
240 | else | 240 | else |
241 | __btrfs_add_free_space(pinned, objectid, 1); | 241 | __btrfs_add_free_space(pinned, objectid, 1); |
242 | 242 | ||
243 | mutex_unlock(&root->fs_commit_mutex); | 243 | up_write(&root->fs_info->commit_root_sem); |
244 | } | 244 | } |
245 | } | 245 | } |
246 | 246 | ||
@@ -250,7 +250,7 @@ again: | |||
250 | * and others will just be dropped, because the commit root we were | 250 | * and others will just be dropped, because the commit root we were |
251 | * searching has changed. | 251 | * searching has changed. |
252 | * | 252 | * |
253 | * Must be called with root->fs_commit_mutex held | 253 | * Must be called with root->fs_info->commit_root_sem held |
254 | */ | 254 | */ |
255 | void btrfs_unpin_free_ino(struct btrfs_root *root) | 255 | void btrfs_unpin_free_ino(struct btrfs_root *root) |
256 | { | 256 | { |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 06e9a4152b14..5f805bc944fa 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -394,6 +394,14 @@ static noinline int compress_file_range(struct inode *inode, | |||
394 | (start > 0 || end + 1 < BTRFS_I(inode)->disk_i_size)) | 394 | (start > 0 || end + 1 < BTRFS_I(inode)->disk_i_size)) |
395 | btrfs_add_inode_defrag(NULL, inode); | 395 | btrfs_add_inode_defrag(NULL, inode); |
396 | 396 | ||
397 | /* | ||
398 | * skip compression for a small file range(<=blocksize) that | ||
399 | * isn't an inline extent, since it dosen't save disk space at all. | ||
400 | */ | ||
401 | if ((end - start + 1) <= blocksize && | ||
402 | (start > 0 || end + 1 < BTRFS_I(inode)->disk_i_size)) | ||
403 | goto cleanup_and_bail_uncompressed; | ||
404 | |||
397 | actual_end = min_t(u64, isize, end + 1); | 405 | actual_end = min_t(u64, isize, end + 1); |
398 | again: | 406 | again: |
399 | will_compress = 0; | 407 | will_compress = 0; |
@@ -1271,6 +1279,15 @@ next_slot: | |||
1271 | disk_bytenr += cur_offset - found_key.offset; | 1279 | disk_bytenr += cur_offset - found_key.offset; |
1272 | num_bytes = min(end + 1, extent_end) - cur_offset; | 1280 | num_bytes = min(end + 1, extent_end) - cur_offset; |
1273 | /* | 1281 | /* |
1282 | * if there are pending snapshots for this root, | ||
1283 | * we fall into common COW way. | ||
1284 | */ | ||
1285 | if (!nolock) { | ||
1286 | err = btrfs_start_nocow_write(root); | ||
1287 | if (!err) | ||
1288 | goto out_check; | ||
1289 | } | ||
1290 | /* | ||
1274 | * force cow if csum exists in the range. | 1291 | * force cow if csum exists in the range. |
1275 | * this ensure that csum for a given extent are | 1292 | * this ensure that csum for a given extent are |
1276 | * either valid or do not exist. | 1293 | * either valid or do not exist. |
@@ -1289,6 +1306,8 @@ next_slot: | |||
1289 | out_check: | 1306 | out_check: |
1290 | if (extent_end <= start) { | 1307 | if (extent_end <= start) { |
1291 | path->slots[0]++; | 1308 | path->slots[0]++; |
1309 | if (!nolock && nocow) | ||
1310 | btrfs_end_nocow_write(root); | ||
1292 | goto next_slot; | 1311 | goto next_slot; |
1293 | } | 1312 | } |
1294 | if (!nocow) { | 1313 | if (!nocow) { |
@@ -1306,8 +1325,11 @@ out_check: | |||
1306 | ret = cow_file_range(inode, locked_page, | 1325 | ret = cow_file_range(inode, locked_page, |
1307 | cow_start, found_key.offset - 1, | 1326 | cow_start, found_key.offset - 1, |
1308 | page_started, nr_written, 1); | 1327 | page_started, nr_written, 1); |
1309 | if (ret) | 1328 | if (ret) { |
1329 | if (!nolock && nocow) | ||
1330 | btrfs_end_nocow_write(root); | ||
1310 | goto error; | 1331 | goto error; |
1332 | } | ||
1311 | cow_start = (u64)-1; | 1333 | cow_start = (u64)-1; |
1312 | } | 1334 | } |
1313 | 1335 | ||
@@ -1354,8 +1376,11 @@ out_check: | |||
1354 | BTRFS_DATA_RELOC_TREE_OBJECTID) { | 1376 | BTRFS_DATA_RELOC_TREE_OBJECTID) { |
1355 | ret = btrfs_reloc_clone_csums(inode, cur_offset, | 1377 | ret = btrfs_reloc_clone_csums(inode, cur_offset, |
1356 | num_bytes); | 1378 | num_bytes); |
1357 | if (ret) | 1379 | if (ret) { |
1380 | if (!nolock && nocow) | ||
1381 | btrfs_end_nocow_write(root); | ||
1358 | goto error; | 1382 | goto error; |
1383 | } | ||
1359 | } | 1384 | } |
1360 | 1385 | ||
1361 | extent_clear_unlock_delalloc(inode, cur_offset, | 1386 | extent_clear_unlock_delalloc(inode, cur_offset, |
@@ -1363,6 +1388,8 @@ out_check: | |||
1363 | locked_page, EXTENT_LOCKED | | 1388 | locked_page, EXTENT_LOCKED | |
1364 | EXTENT_DELALLOC, PAGE_UNLOCK | | 1389 | EXTENT_DELALLOC, PAGE_UNLOCK | |
1365 | PAGE_SET_PRIVATE2); | 1390 | PAGE_SET_PRIVATE2); |
1391 | if (!nolock && nocow) | ||
1392 | btrfs_end_nocow_write(root); | ||
1366 | cur_offset = extent_end; | 1393 | cur_offset = extent_end; |
1367 | if (cur_offset > end) | 1394 | if (cur_offset > end) |
1368 | break; | 1395 | break; |
@@ -8476,19 +8503,20 @@ static int __start_delalloc_inodes(struct btrfs_root *root, int delay_iput, | |||
8476 | else | 8503 | else |
8477 | iput(inode); | 8504 | iput(inode); |
8478 | ret = -ENOMEM; | 8505 | ret = -ENOMEM; |
8479 | break; | 8506 | goto out; |
8480 | } | 8507 | } |
8481 | list_add_tail(&work->list, &works); | 8508 | list_add_tail(&work->list, &works); |
8482 | btrfs_queue_work(root->fs_info->flush_workers, | 8509 | btrfs_queue_work(root->fs_info->flush_workers, |
8483 | &work->work); | 8510 | &work->work); |
8484 | ret++; | 8511 | ret++; |
8485 | if (nr != -1 && ret >= nr) | 8512 | if (nr != -1 && ret >= nr) |
8486 | break; | 8513 | goto out; |
8487 | cond_resched(); | 8514 | cond_resched(); |
8488 | spin_lock(&root->delalloc_lock); | 8515 | spin_lock(&root->delalloc_lock); |
8489 | } | 8516 | } |
8490 | spin_unlock(&root->delalloc_lock); | 8517 | spin_unlock(&root->delalloc_lock); |
8491 | 8518 | ||
8519 | out: | ||
8492 | list_for_each_entry_safe(work, next, &works, list) { | 8520 | list_for_each_entry_safe(work, next, &works, list) { |
8493 | list_del_init(&work->list); | 8521 | list_del_init(&work->list); |
8494 | btrfs_wait_and_free_delalloc_work(work); | 8522 | btrfs_wait_and_free_delalloc_work(work); |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 0401397b5c92..e79ff6b90cb7 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -1472,6 +1472,7 @@ static noinline int btrfs_ioctl_resize(struct file *file, | |||
1472 | struct btrfs_trans_handle *trans; | 1472 | struct btrfs_trans_handle *trans; |
1473 | struct btrfs_device *device = NULL; | 1473 | struct btrfs_device *device = NULL; |
1474 | char *sizestr; | 1474 | char *sizestr; |
1475 | char *retptr; | ||
1475 | char *devstr = NULL; | 1476 | char *devstr = NULL; |
1476 | int ret = 0; | 1477 | int ret = 0; |
1477 | int mod = 0; | 1478 | int mod = 0; |
@@ -1539,8 +1540,8 @@ static noinline int btrfs_ioctl_resize(struct file *file, | |||
1539 | mod = 1; | 1540 | mod = 1; |
1540 | sizestr++; | 1541 | sizestr++; |
1541 | } | 1542 | } |
1542 | new_size = memparse(sizestr, NULL); | 1543 | new_size = memparse(sizestr, &retptr); |
1543 | if (new_size == 0) { | 1544 | if (*retptr != '\0' || new_size == 0) { |
1544 | ret = -EINVAL; | 1545 | ret = -EINVAL; |
1545 | goto out_free; | 1546 | goto out_free; |
1546 | } | 1547 | } |
@@ -3140,8 +3141,9 @@ process_slot: | |||
3140 | new_key.offset + datal, | 3141 | new_key.offset + datal, |
3141 | 1); | 3142 | 1); |
3142 | if (ret) { | 3143 | if (ret) { |
3143 | btrfs_abort_transaction(trans, root, | 3144 | if (ret != -EINVAL) |
3144 | ret); | 3145 | btrfs_abort_transaction(trans, |
3146 | root, ret); | ||
3145 | btrfs_end_transaction(trans, root); | 3147 | btrfs_end_transaction(trans, root); |
3146 | goto out; | 3148 | goto out; |
3147 | } | 3149 | } |
@@ -3538,6 +3540,11 @@ static long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) | |||
3538 | up_read(&info->groups_sem); | 3540 | up_read(&info->groups_sem); |
3539 | } | 3541 | } |
3540 | 3542 | ||
3543 | /* | ||
3544 | * Global block reserve, exported as a space_info | ||
3545 | */ | ||
3546 | slot_count++; | ||
3547 | |||
3541 | /* space_slots == 0 means they are asking for a count */ | 3548 | /* space_slots == 0 means they are asking for a count */ |
3542 | if (space_args.space_slots == 0) { | 3549 | if (space_args.space_slots == 0) { |
3543 | space_args.total_spaces = slot_count; | 3550 | space_args.total_spaces = slot_count; |
@@ -3596,6 +3603,21 @@ static long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) | |||
3596 | up_read(&info->groups_sem); | 3603 | up_read(&info->groups_sem); |
3597 | } | 3604 | } |
3598 | 3605 | ||
3606 | /* | ||
3607 | * Add global block reserve | ||
3608 | */ | ||
3609 | if (slot_count) { | ||
3610 | struct btrfs_block_rsv *block_rsv = &root->fs_info->global_block_rsv; | ||
3611 | |||
3612 | spin_lock(&block_rsv->lock); | ||
3613 | space.total_bytes = block_rsv->size; | ||
3614 | space.used_bytes = block_rsv->size - block_rsv->reserved; | ||
3615 | spin_unlock(&block_rsv->lock); | ||
3616 | space.flags = BTRFS_SPACE_INFO_GLOBAL_RSV; | ||
3617 | memcpy(dest, &space, sizeof(space)); | ||
3618 | space_args.total_spaces++; | ||
3619 | } | ||
3620 | |||
3599 | user_dest = (struct btrfs_ioctl_space_info __user *) | 3621 | user_dest = (struct btrfs_ioctl_space_info __user *) |
3600 | (arg + sizeof(struct btrfs_ioctl_space_args)); | 3622 | (arg + sizeof(struct btrfs_ioctl_space_args)); |
3601 | 3623 | ||
@@ -4531,9 +4553,8 @@ static long btrfs_ioctl_set_received_subvol_32(struct file *file, | |||
4531 | } | 4553 | } |
4532 | 4554 | ||
4533 | args64 = kmalloc(sizeof(*args64), GFP_NOFS); | 4555 | args64 = kmalloc(sizeof(*args64), GFP_NOFS); |
4534 | if (IS_ERR(args64)) { | 4556 | if (!args64) { |
4535 | ret = PTR_ERR(args64); | 4557 | ret = -ENOMEM; |
4536 | args64 = NULL; | ||
4537 | goto out; | 4558 | goto out; |
4538 | } | 4559 | } |
4539 | 4560 | ||
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index def428a25b2a..7f92ab1daa87 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -2317,7 +2317,6 @@ void free_reloc_roots(struct list_head *list) | |||
2317 | static noinline_for_stack | 2317 | static noinline_for_stack |
2318 | int merge_reloc_roots(struct reloc_control *rc) | 2318 | int merge_reloc_roots(struct reloc_control *rc) |
2319 | { | 2319 | { |
2320 | struct btrfs_trans_handle *trans; | ||
2321 | struct btrfs_root *root; | 2320 | struct btrfs_root *root; |
2322 | struct btrfs_root *reloc_root; | 2321 | struct btrfs_root *reloc_root; |
2323 | u64 last_snap; | 2322 | u64 last_snap; |
@@ -2375,26 +2374,6 @@ again: | |||
2375 | list_add_tail(&reloc_root->root_list, | 2374 | list_add_tail(&reloc_root->root_list, |
2376 | &reloc_roots); | 2375 | &reloc_roots); |
2377 | goto out; | 2376 | goto out; |
2378 | } else if (!ret) { | ||
2379 | /* | ||
2380 | * recover the last snapshot tranid to avoid | ||
2381 | * the space balance break NOCOW. | ||
2382 | */ | ||
2383 | root = read_fs_root(rc->extent_root->fs_info, | ||
2384 | objectid); | ||
2385 | if (IS_ERR(root)) | ||
2386 | continue; | ||
2387 | |||
2388 | trans = btrfs_join_transaction(root); | ||
2389 | BUG_ON(IS_ERR(trans)); | ||
2390 | |||
2391 | /* Check if the fs/file tree was snapshoted or not. */ | ||
2392 | if (btrfs_root_last_snapshot(&root->root_item) == | ||
2393 | otransid - 1) | ||
2394 | btrfs_set_root_last_snapshot(&root->root_item, | ||
2395 | last_snap); | ||
2396 | |||
2397 | btrfs_end_transaction(trans, root); | ||
2398 | } | 2377 | } |
2399 | } | 2378 | } |
2400 | 2379 | ||
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 93e6d7172844..0be77993378e 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
@@ -2235,6 +2235,47 @@ behind_scrub_pages: | |||
2235 | return 0; | 2235 | return 0; |
2236 | } | 2236 | } |
2237 | 2237 | ||
2238 | /* | ||
2239 | * Given a physical address, this will calculate it's | ||
2240 | * logical offset. if this is a parity stripe, it will return | ||
2241 | * the most left data stripe's logical offset. | ||
2242 | * | ||
2243 | * return 0 if it is a data stripe, 1 means parity stripe. | ||
2244 | */ | ||
2245 | static int get_raid56_logic_offset(u64 physical, int num, | ||
2246 | struct map_lookup *map, u64 *offset) | ||
2247 | { | ||
2248 | int i; | ||
2249 | int j = 0; | ||
2250 | u64 stripe_nr; | ||
2251 | u64 last_offset; | ||
2252 | int stripe_index; | ||
2253 | int rot; | ||
2254 | |||
2255 | last_offset = (physical - map->stripes[num].physical) * | ||
2256 | nr_data_stripes(map); | ||
2257 | *offset = last_offset; | ||
2258 | for (i = 0; i < nr_data_stripes(map); i++) { | ||
2259 | *offset = last_offset + i * map->stripe_len; | ||
2260 | |||
2261 | stripe_nr = *offset; | ||
2262 | do_div(stripe_nr, map->stripe_len); | ||
2263 | do_div(stripe_nr, nr_data_stripes(map)); | ||
2264 | |||
2265 | /* Work out the disk rotation on this stripe-set */ | ||
2266 | rot = do_div(stripe_nr, map->num_stripes); | ||
2267 | /* calculate which stripe this data locates */ | ||
2268 | rot += i; | ||
2269 | stripe_index = rot % map->num_stripes; | ||
2270 | if (stripe_index == num) | ||
2271 | return 0; | ||
2272 | if (stripe_index < num) | ||
2273 | j++; | ||
2274 | } | ||
2275 | *offset = last_offset + j * map->stripe_len; | ||
2276 | return 1; | ||
2277 | } | ||
2278 | |||
2238 | static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | 2279 | static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, |
2239 | struct map_lookup *map, | 2280 | struct map_lookup *map, |
2240 | struct btrfs_device *scrub_dev, | 2281 | struct btrfs_device *scrub_dev, |
@@ -2256,6 +2297,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
2256 | u64 physical; | 2297 | u64 physical; |
2257 | u64 logical; | 2298 | u64 logical; |
2258 | u64 logic_end; | 2299 | u64 logic_end; |
2300 | u64 physical_end; | ||
2259 | u64 generation; | 2301 | u64 generation; |
2260 | int mirror_num; | 2302 | int mirror_num; |
2261 | struct reada_control *reada1; | 2303 | struct reada_control *reada1; |
@@ -2269,16 +2311,10 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
2269 | u64 extent_len; | 2311 | u64 extent_len; |
2270 | struct btrfs_device *extent_dev; | 2312 | struct btrfs_device *extent_dev; |
2271 | int extent_mirror_num; | 2313 | int extent_mirror_num; |
2272 | int stop_loop; | 2314 | int stop_loop = 0; |
2273 | |||
2274 | if (map->type & (BTRFS_BLOCK_GROUP_RAID5 | | ||
2275 | BTRFS_BLOCK_GROUP_RAID6)) { | ||
2276 | if (num >= nr_data_stripes(map)) { | ||
2277 | return 0; | ||
2278 | } | ||
2279 | } | ||
2280 | 2315 | ||
2281 | nstripes = length; | 2316 | nstripes = length; |
2317 | physical = map->stripes[num].physical; | ||
2282 | offset = 0; | 2318 | offset = 0; |
2283 | do_div(nstripes, map->stripe_len); | 2319 | do_div(nstripes, map->stripe_len); |
2284 | if (map->type & BTRFS_BLOCK_GROUP_RAID0) { | 2320 | if (map->type & BTRFS_BLOCK_GROUP_RAID0) { |
@@ -2296,6 +2332,11 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
2296 | } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { | 2332 | } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { |
2297 | increment = map->stripe_len; | 2333 | increment = map->stripe_len; |
2298 | mirror_num = num % map->num_stripes + 1; | 2334 | mirror_num = num % map->num_stripes + 1; |
2335 | } else if (map->type & (BTRFS_BLOCK_GROUP_RAID5 | | ||
2336 | BTRFS_BLOCK_GROUP_RAID6)) { | ||
2337 | get_raid56_logic_offset(physical, num, map, &offset); | ||
2338 | increment = map->stripe_len * nr_data_stripes(map); | ||
2339 | mirror_num = 1; | ||
2299 | } else { | 2340 | } else { |
2300 | increment = map->stripe_len; | 2341 | increment = map->stripe_len; |
2301 | mirror_num = 1; | 2342 | mirror_num = 1; |
@@ -2319,7 +2360,15 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
2319 | * to not hold off transaction commits | 2360 | * to not hold off transaction commits |
2320 | */ | 2361 | */ |
2321 | logical = base + offset; | 2362 | logical = base + offset; |
2322 | 2363 | physical_end = physical + nstripes * map->stripe_len; | |
2364 | if (map->type & (BTRFS_BLOCK_GROUP_RAID5 | | ||
2365 | BTRFS_BLOCK_GROUP_RAID6)) { | ||
2366 | get_raid56_logic_offset(physical_end, num, | ||
2367 | map, &logic_end); | ||
2368 | logic_end += base; | ||
2369 | } else { | ||
2370 | logic_end = logical + increment * nstripes; | ||
2371 | } | ||
2323 | wait_event(sctx->list_wait, | 2372 | wait_event(sctx->list_wait, |
2324 | atomic_read(&sctx->bios_in_flight) == 0); | 2373 | atomic_read(&sctx->bios_in_flight) == 0); |
2325 | scrub_blocked_if_needed(fs_info); | 2374 | scrub_blocked_if_needed(fs_info); |
@@ -2328,7 +2377,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
2328 | key_start.objectid = logical; | 2377 | key_start.objectid = logical; |
2329 | key_start.type = BTRFS_EXTENT_ITEM_KEY; | 2378 | key_start.type = BTRFS_EXTENT_ITEM_KEY; |
2330 | key_start.offset = (u64)0; | 2379 | key_start.offset = (u64)0; |
2331 | key_end.objectid = base + offset + nstripes * increment; | 2380 | key_end.objectid = logic_end; |
2332 | key_end.type = BTRFS_METADATA_ITEM_KEY; | 2381 | key_end.type = BTRFS_METADATA_ITEM_KEY; |
2333 | key_end.offset = (u64)-1; | 2382 | key_end.offset = (u64)-1; |
2334 | reada1 = btrfs_reada_add(root, &key_start, &key_end); | 2383 | reada1 = btrfs_reada_add(root, &key_start, &key_end); |
@@ -2338,7 +2387,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
2338 | key_start.offset = logical; | 2387 | key_start.offset = logical; |
2339 | key_end.objectid = BTRFS_EXTENT_CSUM_OBJECTID; | 2388 | key_end.objectid = BTRFS_EXTENT_CSUM_OBJECTID; |
2340 | key_end.type = BTRFS_EXTENT_CSUM_KEY; | 2389 | key_end.type = BTRFS_EXTENT_CSUM_KEY; |
2341 | key_end.offset = base + offset + nstripes * increment; | 2390 | key_end.offset = logic_end; |
2342 | reada2 = btrfs_reada_add(csum_root, &key_start, &key_end); | 2391 | reada2 = btrfs_reada_add(csum_root, &key_start, &key_end); |
2343 | 2392 | ||
2344 | if (!IS_ERR(reada1)) | 2393 | if (!IS_ERR(reada1)) |
@@ -2356,11 +2405,17 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, | |||
2356 | /* | 2405 | /* |
2357 | * now find all extents for each stripe and scrub them | 2406 | * now find all extents for each stripe and scrub them |
2358 | */ | 2407 | */ |
2359 | logical = base + offset; | ||
2360 | physical = map->stripes[num].physical; | ||
2361 | logic_end = logical + increment * nstripes; | ||
2362 | ret = 0; | 2408 | ret = 0; |
2363 | while (logical < logic_end) { | 2409 | while (physical < physical_end) { |
2410 | /* for raid56, we skip parity stripe */ | ||
2411 | if (map->type & (BTRFS_BLOCK_GROUP_RAID5 | | ||
2412 | BTRFS_BLOCK_GROUP_RAID6)) { | ||
2413 | ret = get_raid56_logic_offset(physical, num, | ||
2414 | map, &logical); | ||
2415 | logical += base; | ||
2416 | if (ret) | ||
2417 | goto skip; | ||
2418 | } | ||
2364 | /* | 2419 | /* |
2365 | * canceled? | 2420 | * canceled? |
2366 | */ | 2421 | */ |
@@ -2504,15 +2559,29 @@ again: | |||
2504 | scrub_free_csums(sctx); | 2559 | scrub_free_csums(sctx); |
2505 | if (extent_logical + extent_len < | 2560 | if (extent_logical + extent_len < |
2506 | key.objectid + bytes) { | 2561 | key.objectid + bytes) { |
2507 | logical += increment; | 2562 | if (map->type & (BTRFS_BLOCK_GROUP_RAID5 | |
2508 | physical += map->stripe_len; | 2563 | BTRFS_BLOCK_GROUP_RAID6)) { |
2509 | 2564 | /* | |
2565 | * loop until we find next data stripe | ||
2566 | * or we have finished all stripes. | ||
2567 | */ | ||
2568 | do { | ||
2569 | physical += map->stripe_len; | ||
2570 | ret = get_raid56_logic_offset( | ||
2571 | physical, num, | ||
2572 | map, &logical); | ||
2573 | logical += base; | ||
2574 | } while (physical < physical_end && ret); | ||
2575 | } else { | ||
2576 | physical += map->stripe_len; | ||
2577 | logical += increment; | ||
2578 | } | ||
2510 | if (logical < key.objectid + bytes) { | 2579 | if (logical < key.objectid + bytes) { |
2511 | cond_resched(); | 2580 | cond_resched(); |
2512 | goto again; | 2581 | goto again; |
2513 | } | 2582 | } |
2514 | 2583 | ||
2515 | if (logical >= logic_end) { | 2584 | if (physical >= physical_end) { |
2516 | stop_loop = 1; | 2585 | stop_loop = 1; |
2517 | break; | 2586 | break; |
2518 | } | 2587 | } |
@@ -2521,6 +2590,7 @@ next: | |||
2521 | path->slots[0]++; | 2590 | path->slots[0]++; |
2522 | } | 2591 | } |
2523 | btrfs_release_path(path); | 2592 | btrfs_release_path(path); |
2593 | skip: | ||
2524 | logical += increment; | 2594 | logical += increment; |
2525 | physical += map->stripe_len; | 2595 | physical += map->stripe_len; |
2526 | spin_lock(&sctx->stat_lock); | 2596 | spin_lock(&sctx->stat_lock); |
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 9b6da9d55f9a..1ac3ca98c429 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c | |||
@@ -493,6 +493,7 @@ static struct btrfs_path *alloc_path_for_send(void) | |||
493 | return NULL; | 493 | return NULL; |
494 | path->search_commit_root = 1; | 494 | path->search_commit_root = 1; |
495 | path->skip_locking = 1; | 495 | path->skip_locking = 1; |
496 | path->need_commit_sem = 1; | ||
496 | return path; | 497 | return path; |
497 | } | 498 | } |
498 | 499 | ||
@@ -771,29 +772,22 @@ out: | |||
771 | /* | 772 | /* |
772 | * Helper function to retrieve some fields from an inode item. | 773 | * Helper function to retrieve some fields from an inode item. |
773 | */ | 774 | */ |
774 | static int get_inode_info(struct btrfs_root *root, | 775 | static int __get_inode_info(struct btrfs_root *root, struct btrfs_path *path, |
775 | u64 ino, u64 *size, u64 *gen, | 776 | u64 ino, u64 *size, u64 *gen, u64 *mode, u64 *uid, |
776 | u64 *mode, u64 *uid, u64 *gid, | 777 | u64 *gid, u64 *rdev) |
777 | u64 *rdev) | ||
778 | { | 778 | { |
779 | int ret; | 779 | int ret; |
780 | struct btrfs_inode_item *ii; | 780 | struct btrfs_inode_item *ii; |
781 | struct btrfs_key key; | 781 | struct btrfs_key key; |
782 | struct btrfs_path *path; | ||
783 | |||
784 | path = alloc_path_for_send(); | ||
785 | if (!path) | ||
786 | return -ENOMEM; | ||
787 | 782 | ||
788 | key.objectid = ino; | 783 | key.objectid = ino; |
789 | key.type = BTRFS_INODE_ITEM_KEY; | 784 | key.type = BTRFS_INODE_ITEM_KEY; |
790 | key.offset = 0; | 785 | key.offset = 0; |
791 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 786 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
792 | if (ret < 0) | ||
793 | goto out; | ||
794 | if (ret) { | 787 | if (ret) { |
795 | ret = -ENOENT; | 788 | if (ret > 0) |
796 | goto out; | 789 | ret = -ENOENT; |
790 | return ret; | ||
797 | } | 791 | } |
798 | 792 | ||
799 | ii = btrfs_item_ptr(path->nodes[0], path->slots[0], | 793 | ii = btrfs_item_ptr(path->nodes[0], path->slots[0], |
@@ -811,7 +805,22 @@ static int get_inode_info(struct btrfs_root *root, | |||
811 | if (rdev) | 805 | if (rdev) |
812 | *rdev = btrfs_inode_rdev(path->nodes[0], ii); | 806 | *rdev = btrfs_inode_rdev(path->nodes[0], ii); |
813 | 807 | ||
814 | out: | 808 | return ret; |
809 | } | ||
810 | |||
811 | static int get_inode_info(struct btrfs_root *root, | ||
812 | u64 ino, u64 *size, u64 *gen, | ||
813 | u64 *mode, u64 *uid, u64 *gid, | ||
814 | u64 *rdev) | ||
815 | { | ||
816 | struct btrfs_path *path; | ||
817 | int ret; | ||
818 | |||
819 | path = alloc_path_for_send(); | ||
820 | if (!path) | ||
821 | return -ENOMEM; | ||
822 | ret = __get_inode_info(root, path, ino, size, gen, mode, uid, gid, | ||
823 | rdev); | ||
815 | btrfs_free_path(path); | 824 | btrfs_free_path(path); |
816 | return ret; | 825 | return ret; |
817 | } | 826 | } |
@@ -1085,6 +1094,7 @@ out: | |||
1085 | struct backref_ctx { | 1094 | struct backref_ctx { |
1086 | struct send_ctx *sctx; | 1095 | struct send_ctx *sctx; |
1087 | 1096 | ||
1097 | struct btrfs_path *path; | ||
1088 | /* number of total found references */ | 1098 | /* number of total found references */ |
1089 | u64 found; | 1099 | u64 found; |
1090 | 1100 | ||
@@ -1155,8 +1165,9 @@ static int __iterate_backrefs(u64 ino, u64 offset, u64 root, void *ctx_) | |||
1155 | * There are inodes that have extents that lie behind its i_size. Don't | 1165 | * There are inodes that have extents that lie behind its i_size. Don't |
1156 | * accept clones from these extents. | 1166 | * accept clones from these extents. |
1157 | */ | 1167 | */ |
1158 | ret = get_inode_info(found->root, ino, &i_size, NULL, NULL, NULL, NULL, | 1168 | ret = __get_inode_info(found->root, bctx->path, ino, &i_size, NULL, NULL, |
1159 | NULL); | 1169 | NULL, NULL, NULL); |
1170 | btrfs_release_path(bctx->path); | ||
1160 | if (ret < 0) | 1171 | if (ret < 0) |
1161 | return ret; | 1172 | return ret; |
1162 | 1173 | ||
@@ -1235,12 +1246,17 @@ static int find_extent_clone(struct send_ctx *sctx, | |||
1235 | if (!tmp_path) | 1246 | if (!tmp_path) |
1236 | return -ENOMEM; | 1247 | return -ENOMEM; |
1237 | 1248 | ||
1249 | /* We only use this path under the commit sem */ | ||
1250 | tmp_path->need_commit_sem = 0; | ||
1251 | |||
1238 | backref_ctx = kmalloc(sizeof(*backref_ctx), GFP_NOFS); | 1252 | backref_ctx = kmalloc(sizeof(*backref_ctx), GFP_NOFS); |
1239 | if (!backref_ctx) { | 1253 | if (!backref_ctx) { |
1240 | ret = -ENOMEM; | 1254 | ret = -ENOMEM; |
1241 | goto out; | 1255 | goto out; |
1242 | } | 1256 | } |
1243 | 1257 | ||
1258 | backref_ctx->path = tmp_path; | ||
1259 | |||
1244 | if (data_offset >= ino_size) { | 1260 | if (data_offset >= ino_size) { |
1245 | /* | 1261 | /* |
1246 | * There may be extents that lie behind the file's size. | 1262 | * There may be extents that lie behind the file's size. |
@@ -1268,8 +1284,10 @@ static int find_extent_clone(struct send_ctx *sctx, | |||
1268 | } | 1284 | } |
1269 | logical = disk_byte + btrfs_file_extent_offset(eb, fi); | 1285 | logical = disk_byte + btrfs_file_extent_offset(eb, fi); |
1270 | 1286 | ||
1287 | down_read(&sctx->send_root->fs_info->commit_root_sem); | ||
1271 | ret = extent_from_logical(sctx->send_root->fs_info, disk_byte, tmp_path, | 1288 | ret = extent_from_logical(sctx->send_root->fs_info, disk_byte, tmp_path, |
1272 | &found_key, &flags); | 1289 | &found_key, &flags); |
1290 | up_read(&sctx->send_root->fs_info->commit_root_sem); | ||
1273 | btrfs_release_path(tmp_path); | 1291 | btrfs_release_path(tmp_path); |
1274 | 1292 | ||
1275 | if (ret < 0) | 1293 | if (ret < 0) |
@@ -4418,6 +4436,9 @@ static int send_hole(struct send_ctx *sctx, u64 end) | |||
4418 | p = fs_path_alloc(); | 4436 | p = fs_path_alloc(); |
4419 | if (!p) | 4437 | if (!p) |
4420 | return -ENOMEM; | 4438 | return -ENOMEM; |
4439 | ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, p); | ||
4440 | if (ret < 0) | ||
4441 | goto tlv_put_failure; | ||
4421 | memset(sctx->read_buf, 0, BTRFS_SEND_READ_SIZE); | 4442 | memset(sctx->read_buf, 0, BTRFS_SEND_READ_SIZE); |
4422 | while (offset < end) { | 4443 | while (offset < end) { |
4423 | len = min_t(u64, end - offset, BTRFS_SEND_READ_SIZE); | 4444 | len = min_t(u64, end - offset, BTRFS_SEND_READ_SIZE); |
@@ -4425,9 +4446,6 @@ static int send_hole(struct send_ctx *sctx, u64 end) | |||
4425 | ret = begin_cmd(sctx, BTRFS_SEND_C_WRITE); | 4446 | ret = begin_cmd(sctx, BTRFS_SEND_C_WRITE); |
4426 | if (ret < 0) | 4447 | if (ret < 0) |
4427 | break; | 4448 | break; |
4428 | ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, p); | ||
4429 | if (ret < 0) | ||
4430 | break; | ||
4431 | TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p); | 4449 | TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p); |
4432 | TLV_PUT_U64(sctx, BTRFS_SEND_A_FILE_OFFSET, offset); | 4450 | TLV_PUT_U64(sctx, BTRFS_SEND_A_FILE_OFFSET, offset); |
4433 | TLV_PUT(sctx, BTRFS_SEND_A_DATA, sctx->read_buf, len); | 4451 | TLV_PUT(sctx, BTRFS_SEND_A_DATA, sctx->read_buf, len); |
@@ -4968,7 +4986,9 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end) | |||
4968 | 4986 | ||
4969 | if (S_ISREG(sctx->cur_inode_mode)) { | 4987 | if (S_ISREG(sctx->cur_inode_mode)) { |
4970 | if (need_send_hole(sctx)) { | 4988 | if (need_send_hole(sctx)) { |
4971 | if (sctx->cur_inode_last_extent == (u64)-1) { | 4989 | if (sctx->cur_inode_last_extent == (u64)-1 || |
4990 | sctx->cur_inode_last_extent < | ||
4991 | sctx->cur_inode_size) { | ||
4972 | ret = get_last_extent(sctx, (u64)-1); | 4992 | ret = get_last_extent(sctx, (u64)-1); |
4973 | if (ret) | 4993 | if (ret) |
4974 | goto out; | 4994 | goto out; |
@@ -5367,57 +5387,21 @@ out: | |||
5367 | static int full_send_tree(struct send_ctx *sctx) | 5387 | static int full_send_tree(struct send_ctx *sctx) |
5368 | { | 5388 | { |
5369 | int ret; | 5389 | int ret; |
5370 | struct btrfs_trans_handle *trans = NULL; | ||
5371 | struct btrfs_root *send_root = sctx->send_root; | 5390 | struct btrfs_root *send_root = sctx->send_root; |
5372 | struct btrfs_key key; | 5391 | struct btrfs_key key; |
5373 | struct btrfs_key found_key; | 5392 | struct btrfs_key found_key; |
5374 | struct btrfs_path *path; | 5393 | struct btrfs_path *path; |
5375 | struct extent_buffer *eb; | 5394 | struct extent_buffer *eb; |
5376 | int slot; | 5395 | int slot; |
5377 | u64 start_ctransid; | ||
5378 | u64 ctransid; | ||
5379 | 5396 | ||
5380 | path = alloc_path_for_send(); | 5397 | path = alloc_path_for_send(); |
5381 | if (!path) | 5398 | if (!path) |
5382 | return -ENOMEM; | 5399 | return -ENOMEM; |
5383 | 5400 | ||
5384 | spin_lock(&send_root->root_item_lock); | ||
5385 | start_ctransid = btrfs_root_ctransid(&send_root->root_item); | ||
5386 | spin_unlock(&send_root->root_item_lock); | ||
5387 | |||
5388 | key.objectid = BTRFS_FIRST_FREE_OBJECTID; | 5401 | key.objectid = BTRFS_FIRST_FREE_OBJECTID; |
5389 | key.type = BTRFS_INODE_ITEM_KEY; | 5402 | key.type = BTRFS_INODE_ITEM_KEY; |
5390 | key.offset = 0; | 5403 | key.offset = 0; |
5391 | 5404 | ||
5392 | join_trans: | ||
5393 | /* | ||
5394 | * We need to make sure the transaction does not get committed | ||
5395 | * while we do anything on commit roots. Join a transaction to prevent | ||
5396 | * this. | ||
5397 | */ | ||
5398 | trans = btrfs_join_transaction(send_root); | ||
5399 | if (IS_ERR(trans)) { | ||
5400 | ret = PTR_ERR(trans); | ||
5401 | trans = NULL; | ||
5402 | goto out; | ||
5403 | } | ||
5404 | |||
5405 | /* | ||
5406 | * Make sure the tree has not changed after re-joining. We detect this | ||
5407 | * by comparing start_ctransid and ctransid. They should always match. | ||
5408 | */ | ||
5409 | spin_lock(&send_root->root_item_lock); | ||
5410 | ctransid = btrfs_root_ctransid(&send_root->root_item); | ||
5411 | spin_unlock(&send_root->root_item_lock); | ||
5412 | |||
5413 | if (ctransid != start_ctransid) { | ||
5414 | WARN(1, KERN_WARNING "BTRFS: the root that you're trying to " | ||
5415 | "send was modified in between. This is " | ||
5416 | "probably a bug.\n"); | ||
5417 | ret = -EIO; | ||
5418 | goto out; | ||
5419 | } | ||
5420 | |||
5421 | ret = btrfs_search_slot_for_read(send_root, &key, path, 1, 0); | 5405 | ret = btrfs_search_slot_for_read(send_root, &key, path, 1, 0); |
5422 | if (ret < 0) | 5406 | if (ret < 0) |
5423 | goto out; | 5407 | goto out; |
@@ -5425,19 +5409,6 @@ join_trans: | |||
5425 | goto out_finish; | 5409 | goto out_finish; |
5426 | 5410 | ||
5427 | while (1) { | 5411 | while (1) { |
5428 | /* | ||
5429 | * When someone want to commit while we iterate, end the | ||
5430 | * joined transaction and rejoin. | ||
5431 | */ | ||
5432 | if (btrfs_should_end_transaction(trans, send_root)) { | ||
5433 | ret = btrfs_end_transaction(trans, send_root); | ||
5434 | trans = NULL; | ||
5435 | if (ret < 0) | ||
5436 | goto out; | ||
5437 | btrfs_release_path(path); | ||
5438 | goto join_trans; | ||
5439 | } | ||
5440 | |||
5441 | eb = path->nodes[0]; | 5412 | eb = path->nodes[0]; |
5442 | slot = path->slots[0]; | 5413 | slot = path->slots[0]; |
5443 | btrfs_item_key_to_cpu(eb, &found_key, slot); | 5414 | btrfs_item_key_to_cpu(eb, &found_key, slot); |
@@ -5465,12 +5436,6 @@ out_finish: | |||
5465 | 5436 | ||
5466 | out: | 5437 | out: |
5467 | btrfs_free_path(path); | 5438 | btrfs_free_path(path); |
5468 | if (trans) { | ||
5469 | if (!ret) | ||
5470 | ret = btrfs_end_transaction(trans, send_root); | ||
5471 | else | ||
5472 | btrfs_end_transaction(trans, send_root); | ||
5473 | } | ||
5474 | return ret; | 5439 | return ret; |
5475 | } | 5440 | } |
5476 | 5441 | ||
@@ -5718,7 +5683,9 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_) | |||
5718 | NULL); | 5683 | NULL); |
5719 | sort_clone_roots = 1; | 5684 | sort_clone_roots = 1; |
5720 | 5685 | ||
5686 | current->journal_info = (void *)BTRFS_SEND_TRANS_STUB; | ||
5721 | ret = send_subvol(sctx); | 5687 | ret = send_subvol(sctx); |
5688 | current->journal_info = NULL; | ||
5722 | if (ret < 0) | 5689 | if (ret < 0) |
5723 | goto out; | 5690 | goto out; |
5724 | 5691 | ||
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 9dbf42395153..5011aadacab8 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -66,6 +66,8 @@ | |||
66 | static const struct super_operations btrfs_super_ops; | 66 | static const struct super_operations btrfs_super_ops; |
67 | static struct file_system_type btrfs_fs_type; | 67 | static struct file_system_type btrfs_fs_type; |
68 | 68 | ||
69 | static int btrfs_remount(struct super_block *sb, int *flags, char *data); | ||
70 | |||
69 | static const char *btrfs_decode_error(int errno) | 71 | static const char *btrfs_decode_error(int errno) |
70 | { | 72 | { |
71 | char *errstr = "unknown"; | 73 | char *errstr = "unknown"; |
@@ -1185,6 +1187,26 @@ static struct dentry *mount_subvol(const char *subvol_name, int flags, | |||
1185 | mnt = vfs_kern_mount(&btrfs_fs_type, flags, device_name, | 1187 | mnt = vfs_kern_mount(&btrfs_fs_type, flags, device_name, |
1186 | newargs); | 1188 | newargs); |
1187 | kfree(newargs); | 1189 | kfree(newargs); |
1190 | |||
1191 | if (PTR_RET(mnt) == -EBUSY) { | ||
1192 | if (flags & MS_RDONLY) { | ||
1193 | mnt = vfs_kern_mount(&btrfs_fs_type, flags & ~MS_RDONLY, device_name, | ||
1194 | newargs); | ||
1195 | } else { | ||
1196 | int r; | ||
1197 | mnt = vfs_kern_mount(&btrfs_fs_type, flags | MS_RDONLY, device_name, | ||
1198 | newargs); | ||
1199 | if (IS_ERR(mnt)) | ||
1200 | return ERR_CAST(mnt); | ||
1201 | |||
1202 | r = btrfs_remount(mnt->mnt_sb, &flags, NULL); | ||
1203 | if (r < 0) { | ||
1204 | /* FIXME: release vfsmount mnt ??*/ | ||
1205 | return ERR_PTR(r); | ||
1206 | } | ||
1207 | } | ||
1208 | } | ||
1209 | |||
1188 | if (IS_ERR(mnt)) | 1210 | if (IS_ERR(mnt)) |
1189 | return ERR_CAST(mnt); | 1211 | return ERR_CAST(mnt); |
1190 | 1212 | ||
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index a04707f740d6..7579f6d0b854 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -75,10 +75,21 @@ void btrfs_put_transaction(struct btrfs_transaction *transaction) | |||
75 | } | 75 | } |
76 | } | 76 | } |
77 | 77 | ||
78 | static noinline void switch_commit_root(struct btrfs_root *root) | 78 | static noinline void switch_commit_roots(struct btrfs_transaction *trans, |
79 | struct btrfs_fs_info *fs_info) | ||
79 | { | 80 | { |
80 | free_extent_buffer(root->commit_root); | 81 | struct btrfs_root *root, *tmp; |
81 | root->commit_root = btrfs_root_node(root); | 82 | |
83 | down_write(&fs_info->commit_root_sem); | ||
84 | list_for_each_entry_safe(root, tmp, &trans->switch_commits, | ||
85 | dirty_list) { | ||
86 | list_del_init(&root->dirty_list); | ||
87 | free_extent_buffer(root->commit_root); | ||
88 | root->commit_root = btrfs_root_node(root); | ||
89 | if (is_fstree(root->objectid)) | ||
90 | btrfs_unpin_free_ino(root); | ||
91 | } | ||
92 | up_write(&fs_info->commit_root_sem); | ||
82 | } | 93 | } |
83 | 94 | ||
84 | static inline void extwriter_counter_inc(struct btrfs_transaction *trans, | 95 | static inline void extwriter_counter_inc(struct btrfs_transaction *trans, |
@@ -208,6 +219,7 @@ loop: | |||
208 | INIT_LIST_HEAD(&cur_trans->pending_snapshots); | 219 | INIT_LIST_HEAD(&cur_trans->pending_snapshots); |
209 | INIT_LIST_HEAD(&cur_trans->ordered_operations); | 220 | INIT_LIST_HEAD(&cur_trans->ordered_operations); |
210 | INIT_LIST_HEAD(&cur_trans->pending_chunks); | 221 | INIT_LIST_HEAD(&cur_trans->pending_chunks); |
222 | INIT_LIST_HEAD(&cur_trans->switch_commits); | ||
211 | list_add_tail(&cur_trans->list, &fs_info->trans_list); | 223 | list_add_tail(&cur_trans->list, &fs_info->trans_list); |
212 | extent_io_tree_init(&cur_trans->dirty_pages, | 224 | extent_io_tree_init(&cur_trans->dirty_pages, |
213 | fs_info->btree_inode->i_mapping); | 225 | fs_info->btree_inode->i_mapping); |
@@ -375,7 +387,8 @@ start_transaction(struct btrfs_root *root, u64 num_items, unsigned int type, | |||
375 | if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state)) | 387 | if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state)) |
376 | return ERR_PTR(-EROFS); | 388 | return ERR_PTR(-EROFS); |
377 | 389 | ||
378 | if (current->journal_info) { | 390 | if (current->journal_info && |
391 | current->journal_info != (void *)BTRFS_SEND_TRANS_STUB) { | ||
379 | WARN_ON(type & TRANS_EXTWRITERS); | 392 | WARN_ON(type & TRANS_EXTWRITERS); |
380 | h = current->journal_info; | 393 | h = current->journal_info; |
381 | h->use_count++; | 394 | h->use_count++; |
@@ -919,9 +932,6 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans, | |||
919 | return ret; | 932 | return ret; |
920 | } | 933 | } |
921 | 934 | ||
922 | if (root != root->fs_info->extent_root) | ||
923 | switch_commit_root(root); | ||
924 | |||
925 | return 0; | 935 | return 0; |
926 | } | 936 | } |
927 | 937 | ||
@@ -977,15 +987,16 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans, | |||
977 | list_del_init(next); | 987 | list_del_init(next); |
978 | root = list_entry(next, struct btrfs_root, dirty_list); | 988 | root = list_entry(next, struct btrfs_root, dirty_list); |
979 | 989 | ||
990 | if (root != fs_info->extent_root) | ||
991 | list_add_tail(&root->dirty_list, | ||
992 | &trans->transaction->switch_commits); | ||
980 | ret = update_cowonly_root(trans, root); | 993 | ret = update_cowonly_root(trans, root); |
981 | if (ret) | 994 | if (ret) |
982 | return ret; | 995 | return ret; |
983 | } | 996 | } |
984 | 997 | ||
985 | down_write(&fs_info->extent_commit_sem); | 998 | list_add_tail(&fs_info->extent_root->dirty_list, |
986 | switch_commit_root(fs_info->extent_root); | 999 | &trans->transaction->switch_commits); |
987 | up_write(&fs_info->extent_commit_sem); | ||
988 | |||
989 | btrfs_after_dev_replace_commit(fs_info); | 1000 | btrfs_after_dev_replace_commit(fs_info); |
990 | 1001 | ||
991 | return 0; | 1002 | return 0; |
@@ -1042,11 +1053,8 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans, | |||
1042 | smp_wmb(); | 1053 | smp_wmb(); |
1043 | 1054 | ||
1044 | if (root->commit_root != root->node) { | 1055 | if (root->commit_root != root->node) { |
1045 | mutex_lock(&root->fs_commit_mutex); | 1056 | list_add_tail(&root->dirty_list, |
1046 | switch_commit_root(root); | 1057 | &trans->transaction->switch_commits); |
1047 | btrfs_unpin_free_ino(root); | ||
1048 | mutex_unlock(&root->fs_commit_mutex); | ||
1049 | |||
1050 | btrfs_set_root_node(&root->root_item, | 1058 | btrfs_set_root_node(&root->root_item, |
1051 | root->node); | 1059 | root->node); |
1052 | } | 1060 | } |
@@ -1857,11 +1865,15 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1857 | 1865 | ||
1858 | btrfs_set_root_node(&root->fs_info->tree_root->root_item, | 1866 | btrfs_set_root_node(&root->fs_info->tree_root->root_item, |
1859 | root->fs_info->tree_root->node); | 1867 | root->fs_info->tree_root->node); |
1860 | switch_commit_root(root->fs_info->tree_root); | 1868 | list_add_tail(&root->fs_info->tree_root->dirty_list, |
1869 | &cur_trans->switch_commits); | ||
1861 | 1870 | ||
1862 | btrfs_set_root_node(&root->fs_info->chunk_root->root_item, | 1871 | btrfs_set_root_node(&root->fs_info->chunk_root->root_item, |
1863 | root->fs_info->chunk_root->node); | 1872 | root->fs_info->chunk_root->node); |
1864 | switch_commit_root(root->fs_info->chunk_root); | 1873 | list_add_tail(&root->fs_info->chunk_root->dirty_list, |
1874 | &cur_trans->switch_commits); | ||
1875 | |||
1876 | switch_commit_roots(cur_trans, root->fs_info); | ||
1865 | 1877 | ||
1866 | assert_qgroups_uptodate(trans); | 1878 | assert_qgroups_uptodate(trans); |
1867 | update_super_roots(root); | 1879 | update_super_roots(root); |
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index 6ac037e9f9f0..b57b924e8e03 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
@@ -57,6 +57,7 @@ struct btrfs_transaction { | |||
57 | struct list_head pending_snapshots; | 57 | struct list_head pending_snapshots; |
58 | struct list_head ordered_operations; | 58 | struct list_head ordered_operations; |
59 | struct list_head pending_chunks; | 59 | struct list_head pending_chunks; |
60 | struct list_head switch_commits; | ||
60 | struct btrfs_delayed_ref_root delayed_refs; | 61 | struct btrfs_delayed_ref_root delayed_refs; |
61 | int aborted; | 62 | int aborted; |
62 | }; | 63 | }; |
@@ -78,6 +79,8 @@ struct btrfs_transaction { | |||
78 | #define TRANS_EXTWRITERS (__TRANS_USERSPACE | __TRANS_START | \ | 79 | #define TRANS_EXTWRITERS (__TRANS_USERSPACE | __TRANS_START | \ |
79 | __TRANS_ATTACH) | 80 | __TRANS_ATTACH) |
80 | 81 | ||
82 | #define BTRFS_SEND_TRANS_STUB 1 | ||
83 | |||
81 | struct btrfs_trans_handle { | 84 | struct btrfs_trans_handle { |
82 | u64 transid; | 85 | u64 transid; |
83 | u64 bytes_reserved; | 86 | u64 bytes_reserved; |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index d241130a32fd..49d7fab73360 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -448,6 +448,14 @@ static void pending_bios_fn(struct btrfs_work *work) | |||
448 | run_scheduled_bios(device); | 448 | run_scheduled_bios(device); |
449 | } | 449 | } |
450 | 450 | ||
451 | /* | ||
452 | * Add new device to list of registered devices | ||
453 | * | ||
454 | * Returns: | ||
455 | * 1 - first time device is seen | ||
456 | * 0 - device already known | ||
457 | * < 0 - error | ||
458 | */ | ||
451 | static noinline int device_list_add(const char *path, | 459 | static noinline int device_list_add(const char *path, |
452 | struct btrfs_super_block *disk_super, | 460 | struct btrfs_super_block *disk_super, |
453 | u64 devid, struct btrfs_fs_devices **fs_devices_ret) | 461 | u64 devid, struct btrfs_fs_devices **fs_devices_ret) |
@@ -455,6 +463,7 @@ static noinline int device_list_add(const char *path, | |||
455 | struct btrfs_device *device; | 463 | struct btrfs_device *device; |
456 | struct btrfs_fs_devices *fs_devices; | 464 | struct btrfs_fs_devices *fs_devices; |
457 | struct rcu_string *name; | 465 | struct rcu_string *name; |
466 | int ret = 0; | ||
458 | u64 found_transid = btrfs_super_generation(disk_super); | 467 | u64 found_transid = btrfs_super_generation(disk_super); |
459 | 468 | ||
460 | fs_devices = find_fsid(disk_super->fsid); | 469 | fs_devices = find_fsid(disk_super->fsid); |
@@ -495,6 +504,7 @@ static noinline int device_list_add(const char *path, | |||
495 | fs_devices->num_devices++; | 504 | fs_devices->num_devices++; |
496 | mutex_unlock(&fs_devices->device_list_mutex); | 505 | mutex_unlock(&fs_devices->device_list_mutex); |
497 | 506 | ||
507 | ret = 1; | ||
498 | device->fs_devices = fs_devices; | 508 | device->fs_devices = fs_devices; |
499 | } else if (!device->name || strcmp(device->name->str, path)) { | 509 | } else if (!device->name || strcmp(device->name->str, path)) { |
500 | name = rcu_string_strdup(path, GFP_NOFS); | 510 | name = rcu_string_strdup(path, GFP_NOFS); |
@@ -513,7 +523,8 @@ static noinline int device_list_add(const char *path, | |||
513 | fs_devices->latest_trans = found_transid; | 523 | fs_devices->latest_trans = found_transid; |
514 | } | 524 | } |
515 | *fs_devices_ret = fs_devices; | 525 | *fs_devices_ret = fs_devices; |
516 | return 0; | 526 | |
527 | return ret; | ||
517 | } | 528 | } |
518 | 529 | ||
519 | static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig) | 530 | static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig) |
@@ -910,17 +921,19 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder, | |||
910 | transid = btrfs_super_generation(disk_super); | 921 | transid = btrfs_super_generation(disk_super); |
911 | total_devices = btrfs_super_num_devices(disk_super); | 922 | total_devices = btrfs_super_num_devices(disk_super); |
912 | 923 | ||
913 | if (disk_super->label[0]) { | ||
914 | if (disk_super->label[BTRFS_LABEL_SIZE - 1]) | ||
915 | disk_super->label[BTRFS_LABEL_SIZE - 1] = '\0'; | ||
916 | printk(KERN_INFO "BTRFS: device label %s ", disk_super->label); | ||
917 | } else { | ||
918 | printk(KERN_INFO "BTRFS: device fsid %pU ", disk_super->fsid); | ||
919 | } | ||
920 | |||
921 | printk(KERN_CONT "devid %llu transid %llu %s\n", devid, transid, path); | ||
922 | |||
923 | ret = device_list_add(path, disk_super, devid, fs_devices_ret); | 924 | ret = device_list_add(path, disk_super, devid, fs_devices_ret); |
925 | if (ret > 0) { | ||
926 | if (disk_super->label[0]) { | ||
927 | if (disk_super->label[BTRFS_LABEL_SIZE - 1]) | ||
928 | disk_super->label[BTRFS_LABEL_SIZE - 1] = '\0'; | ||
929 | printk(KERN_INFO "BTRFS: device label %s ", disk_super->label); | ||
930 | } else { | ||
931 | printk(KERN_INFO "BTRFS: device fsid %pU ", disk_super->fsid); | ||
932 | } | ||
933 | |||
934 | printk(KERN_CONT "devid %llu transid %llu %s\n", devid, transid, path); | ||
935 | ret = 0; | ||
936 | } | ||
924 | if (!ret && fs_devices_ret) | 937 | if (!ret && fs_devices_ret) |
925 | (*fs_devices_ret)->total_devices = total_devices; | 938 | (*fs_devices_ret)->total_devices = total_devices; |
926 | 939 | ||
diff --git a/fs/buffer.c b/fs/buffer.c index 8c53a2b15ecb..9ddb9fc7d923 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -2114,8 +2114,8 @@ EXPORT_SYMBOL(generic_write_end); | |||
2114 | * Returns true if all buffers which correspond to a file portion | 2114 | * Returns true if all buffers which correspond to a file portion |
2115 | * we want to read are uptodate. | 2115 | * we want to read are uptodate. |
2116 | */ | 2116 | */ |
2117 | int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc, | 2117 | int block_is_partially_uptodate(struct page *page, unsigned long from, |
2118 | unsigned long from) | 2118 | unsigned long count) |
2119 | { | 2119 | { |
2120 | unsigned block_start, block_end, blocksize; | 2120 | unsigned block_start, block_end, blocksize; |
2121 | unsigned to; | 2121 | unsigned to; |
@@ -2127,7 +2127,7 @@ int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc, | |||
2127 | 2127 | ||
2128 | head = page_buffers(page); | 2128 | head = page_buffers(page); |
2129 | blocksize = head->b_size; | 2129 | blocksize = head->b_size; |
2130 | to = min_t(unsigned, PAGE_CACHE_SIZE - from, desc->count); | 2130 | to = min_t(unsigned, PAGE_CACHE_SIZE - from, count); |
2131 | to = from + to; | 2131 | to = from + to; |
2132 | if (from < blocksize && to > PAGE_CACHE_SIZE - blocksize) | 2132 | if (from < blocksize && to > PAGE_CACHE_SIZE - blocksize) |
2133 | return 0; | 2133 | return 0; |
diff --git a/fs/cachefiles/bind.c b/fs/cachefiles/bind.c index 622f4696e484..5b99bafc31d1 100644 --- a/fs/cachefiles/bind.c +++ b/fs/cachefiles/bind.c | |||
@@ -124,7 +124,6 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache) | |||
124 | /* check parameters */ | 124 | /* check parameters */ |
125 | ret = -EOPNOTSUPP; | 125 | ret = -EOPNOTSUPP; |
126 | if (!root->d_inode || | 126 | if (!root->d_inode || |
127 | !root->d_inode->i_op || | ||
128 | !root->d_inode->i_op->lookup || | 127 | !root->d_inode->i_op->lookup || |
129 | !root->d_inode->i_op->mkdir || | 128 | !root->d_inode->i_op->mkdir || |
130 | !root->d_inode->i_op->setxattr || | 129 | !root->d_inode->i_op->setxattr || |
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index 6494d9f673aa..c0a681705104 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c | |||
@@ -779,8 +779,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache, | |||
779 | } | 779 | } |
780 | 780 | ||
781 | ret = -EPERM; | 781 | ret = -EPERM; |
782 | if (!subdir->d_inode->i_op || | 782 | if (!subdir->d_inode->i_op->setxattr || |
783 | !subdir->d_inode->i_op->setxattr || | ||
784 | !subdir->d_inode->i_op->getxattr || | 783 | !subdir->d_inode->i_op->getxattr || |
785 | !subdir->d_inode->i_op->lookup || | 784 | !subdir->d_inode->i_op->lookup || |
786 | !subdir->d_inode->i_op->mkdir || | 785 | !subdir->d_inode->i_op->mkdir || |
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 66075a4ad979..39da1c2efa50 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -601,7 +601,7 @@ ceph_sync_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
601 | false); | 601 | false); |
602 | if (IS_ERR(req)) { | 602 | if (IS_ERR(req)) { |
603 | ret = PTR_ERR(req); | 603 | ret = PTR_ERR(req); |
604 | goto out; | 604 | break; |
605 | } | 605 | } |
606 | 606 | ||
607 | num_pages = calc_pages_for(page_align, len); | 607 | num_pages = calc_pages_for(page_align, len); |
@@ -719,7 +719,7 @@ static ssize_t ceph_sync_write(struct kiocb *iocb, const struct iovec *iov, | |||
719 | false); | 719 | false); |
720 | if (IS_ERR(req)) { | 720 | if (IS_ERR(req)) { |
721 | ret = PTR_ERR(req); | 721 | ret = PTR_ERR(req); |
722 | goto out; | 722 | break; |
723 | } | 723 | } |
724 | 724 | ||
725 | /* | 725 | /* |
@@ -972,6 +972,7 @@ retry_snap: | |||
972 | } | 972 | } |
973 | } else { | 973 | } else { |
974 | loff_t old_size = inode->i_size; | 974 | loff_t old_size = inode->i_size; |
975 | struct iov_iter from; | ||
975 | /* | 976 | /* |
976 | * No need to acquire the i_truncate_mutex. Because | 977 | * No need to acquire the i_truncate_mutex. Because |
977 | * the MDS revokes Fwb caps before sending truncate | 978 | * the MDS revokes Fwb caps before sending truncate |
@@ -979,9 +980,10 @@ retry_snap: | |||
979 | * are pending vmtruncate. So write and vmtruncate | 980 | * are pending vmtruncate. So write and vmtruncate |
980 | * can not run at the same time | 981 | * can not run at the same time |
981 | */ | 982 | */ |
982 | written = generic_file_buffered_write(iocb, iov, nr_segs, | 983 | iov_iter_init(&from, iov, nr_segs, count, 0); |
983 | pos, &iocb->ki_pos, | 984 | written = generic_perform_write(file, &from, pos); |
984 | count, 0); | 985 | if (likely(written >= 0)) |
986 | iocb->ki_pos = pos + written; | ||
985 | if (inode->i_size > old_size) | 987 | if (inode->i_size > old_size) |
986 | ceph_fscache_update_objectsize(inode); | 988 | ceph_fscache_update_objectsize(inode); |
987 | mutex_unlock(&inode->i_mutex); | 989 | mutex_unlock(&inode->i_mutex); |
diff --git a/fs/ceph/ioctl.c b/fs/ceph/ioctl.c index efbe08289292..fdf941b44ff1 100644 --- a/fs/ceph/ioctl.c +++ b/fs/ceph/ioctl.c | |||
@@ -1,9 +1,8 @@ | |||
1 | #include <linux/ceph/ceph_debug.h> | ||
1 | #include <linux/in.h> | 2 | #include <linux/in.h> |
2 | 3 | ||
3 | #include "super.h" | 4 | #include "super.h" |
4 | #include "mds_client.h" | 5 | #include "mds_client.h" |
5 | #include <linux/ceph/ceph_debug.h> | ||
6 | |||
7 | #include "ioctl.h" | 6 | #include "ioctl.h" |
8 | 7 | ||
9 | 8 | ||
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 2c70cbe35d39..df9c9141c099 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -850,7 +850,6 @@ const struct inode_operations cifs_file_inode_ops = { | |||
850 | /* revalidate:cifs_revalidate, */ | 850 | /* revalidate:cifs_revalidate, */ |
851 | .setattr = cifs_setattr, | 851 | .setattr = cifs_setattr, |
852 | .getattr = cifs_getattr, /* do we need this anymore? */ | 852 | .getattr = cifs_getattr, /* do we need this anymore? */ |
853 | .rename = cifs_rename, | ||
854 | .permission = cifs_permission, | 853 | .permission = cifs_permission, |
855 | #ifdef CONFIG_CIFS_XATTR | 854 | #ifdef CONFIG_CIFS_XATTR |
856 | .setxattr = cifs_setxattr, | 855 | .setxattr = cifs_setxattr, |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 216d7e99f921..8807442c94dd 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -2579,19 +2579,32 @@ cifs_writev(struct kiocb *iocb, const struct iovec *iov, | |||
2579 | struct cifsInodeInfo *cinode = CIFS_I(inode); | 2579 | struct cifsInodeInfo *cinode = CIFS_I(inode); |
2580 | struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; | 2580 | struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; |
2581 | ssize_t rc = -EACCES; | 2581 | ssize_t rc = -EACCES; |
2582 | loff_t lock_pos = pos; | 2582 | loff_t lock_pos = iocb->ki_pos; |
2583 | 2583 | ||
2584 | if (file->f_flags & O_APPEND) | ||
2585 | lock_pos = i_size_read(inode); | ||
2586 | /* | 2584 | /* |
2587 | * We need to hold the sem to be sure nobody modifies lock list | 2585 | * We need to hold the sem to be sure nobody modifies lock list |
2588 | * with a brlock that prevents writing. | 2586 | * with a brlock that prevents writing. |
2589 | */ | 2587 | */ |
2590 | down_read(&cinode->lock_sem); | 2588 | down_read(&cinode->lock_sem); |
2589 | mutex_lock(&inode->i_mutex); | ||
2590 | if (file->f_flags & O_APPEND) | ||
2591 | lock_pos = i_size_read(inode); | ||
2591 | if (!cifs_find_lock_conflict(cfile, lock_pos, iov_length(iov, nr_segs), | 2592 | if (!cifs_find_lock_conflict(cfile, lock_pos, iov_length(iov, nr_segs), |
2592 | server->vals->exclusive_lock_type, NULL, | 2593 | server->vals->exclusive_lock_type, NULL, |
2593 | CIFS_WRITE_OP)) | 2594 | CIFS_WRITE_OP)) { |
2594 | rc = generic_file_aio_write(iocb, iov, nr_segs, pos); | 2595 | rc = __generic_file_aio_write(iocb, iov, nr_segs); |
2596 | mutex_unlock(&inode->i_mutex); | ||
2597 | |||
2598 | if (rc > 0) { | ||
2599 | ssize_t err; | ||
2600 | |||
2601 | err = generic_write_sync(file, iocb->ki_pos - rc, rc); | ||
2602 | if (rc < 0) | ||
2603 | rc = err; | ||
2604 | } | ||
2605 | } else { | ||
2606 | mutex_unlock(&inode->i_mutex); | ||
2607 | } | ||
2595 | up_read(&cinode->lock_sem); | 2608 | up_read(&cinode->lock_sem); |
2596 | return rc; | 2609 | return rc; |
2597 | } | 2610 | } |
@@ -2727,56 +2740,27 @@ cifs_retry_async_readv(struct cifs_readdata *rdata) | |||
2727 | /** | 2740 | /** |
2728 | * cifs_readdata_to_iov - copy data from pages in response to an iovec | 2741 | * cifs_readdata_to_iov - copy data from pages in response to an iovec |
2729 | * @rdata: the readdata response with list of pages holding data | 2742 | * @rdata: the readdata response with list of pages holding data |
2730 | * @iov: vector in which we should copy the data | 2743 | * @iter: destination for our data |
2731 | * @nr_segs: number of segments in vector | ||
2732 | * @offset: offset into file of the first iovec | ||
2733 | * @copied: used to return the amount of data copied to the iov | ||
2734 | * | 2744 | * |
2735 | * This function copies data from a list of pages in a readdata response into | 2745 | * This function copies data from a list of pages in a readdata response into |
2736 | * an array of iovecs. It will first calculate where the data should go | 2746 | * an array of iovecs. It will first calculate where the data should go |
2737 | * based on the info in the readdata and then copy the data into that spot. | 2747 | * based on the info in the readdata and then copy the data into that spot. |
2738 | */ | 2748 | */ |
2739 | static ssize_t | 2749 | static int |
2740 | cifs_readdata_to_iov(struct cifs_readdata *rdata, const struct iovec *iov, | 2750 | cifs_readdata_to_iov(struct cifs_readdata *rdata, struct iov_iter *iter) |
2741 | unsigned long nr_segs, loff_t offset, ssize_t *copied) | ||
2742 | { | 2751 | { |
2743 | int rc = 0; | 2752 | size_t remaining = rdata->bytes; |
2744 | struct iov_iter ii; | ||
2745 | size_t pos = rdata->offset - offset; | ||
2746 | ssize_t remaining = rdata->bytes; | ||
2747 | unsigned char *pdata; | ||
2748 | unsigned int i; | 2753 | unsigned int i; |
2749 | 2754 | ||
2750 | /* set up iov_iter and advance to the correct offset */ | ||
2751 | iov_iter_init(&ii, iov, nr_segs, iov_length(iov, nr_segs), 0); | ||
2752 | iov_iter_advance(&ii, pos); | ||
2753 | |||
2754 | *copied = 0; | ||
2755 | for (i = 0; i < rdata->nr_pages; i++) { | 2755 | for (i = 0; i < rdata->nr_pages; i++) { |
2756 | ssize_t copy; | ||
2757 | struct page *page = rdata->pages[i]; | 2756 | struct page *page = rdata->pages[i]; |
2758 | 2757 | size_t copy = min(remaining, PAGE_SIZE); | |
2759 | /* copy a whole page or whatever's left */ | 2758 | size_t written = copy_page_to_iter(page, 0, copy, iter); |
2760 | copy = min_t(ssize_t, remaining, PAGE_SIZE); | 2759 | remaining -= written; |
2761 | 2760 | if (written < copy && iov_iter_count(iter) > 0) | |
2762 | /* ...but limit it to whatever space is left in the iov */ | 2761 | break; |
2763 | copy = min_t(ssize_t, copy, iov_iter_count(&ii)); | ||
2764 | |||
2765 | /* go while there's data to be copied and no errors */ | ||
2766 | if (copy && !rc) { | ||
2767 | pdata = kmap(page); | ||
2768 | rc = memcpy_toiovecend(ii.iov, pdata, ii.iov_offset, | ||
2769 | (int)copy); | ||
2770 | kunmap(page); | ||
2771 | if (!rc) { | ||
2772 | *copied += copy; | ||
2773 | remaining -= copy; | ||
2774 | iov_iter_advance(&ii, copy); | ||
2775 | } | ||
2776 | } | ||
2777 | } | 2762 | } |
2778 | 2763 | return remaining ? -EFAULT : 0; | |
2779 | return rc; | ||
2780 | } | 2764 | } |
2781 | 2765 | ||
2782 | static void | 2766 | static void |
@@ -2837,20 +2821,21 @@ cifs_uncached_read_into_pages(struct TCP_Server_Info *server, | |||
2837 | return total_read > 0 ? total_read : result; | 2821 | return total_read > 0 ? total_read : result; |
2838 | } | 2822 | } |
2839 | 2823 | ||
2840 | static ssize_t | 2824 | ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, |
2841 | cifs_iovec_read(struct file *file, const struct iovec *iov, | 2825 | unsigned long nr_segs, loff_t pos) |
2842 | unsigned long nr_segs, loff_t *poffset) | ||
2843 | { | 2826 | { |
2827 | struct file *file = iocb->ki_filp; | ||
2844 | ssize_t rc; | 2828 | ssize_t rc; |
2845 | size_t len, cur_len; | 2829 | size_t len, cur_len; |
2846 | ssize_t total_read = 0; | 2830 | ssize_t total_read = 0; |
2847 | loff_t offset = *poffset; | 2831 | loff_t offset = pos; |
2848 | unsigned int npages; | 2832 | unsigned int npages; |
2849 | struct cifs_sb_info *cifs_sb; | 2833 | struct cifs_sb_info *cifs_sb; |
2850 | struct cifs_tcon *tcon; | 2834 | struct cifs_tcon *tcon; |
2851 | struct cifsFileInfo *open_file; | 2835 | struct cifsFileInfo *open_file; |
2852 | struct cifs_readdata *rdata, *tmp; | 2836 | struct cifs_readdata *rdata, *tmp; |
2853 | struct list_head rdata_list; | 2837 | struct list_head rdata_list; |
2838 | struct iov_iter to; | ||
2854 | pid_t pid; | 2839 | pid_t pid; |
2855 | 2840 | ||
2856 | if (!nr_segs) | 2841 | if (!nr_segs) |
@@ -2860,6 +2845,8 @@ cifs_iovec_read(struct file *file, const struct iovec *iov, | |||
2860 | if (!len) | 2845 | if (!len) |
2861 | return 0; | 2846 | return 0; |
2862 | 2847 | ||
2848 | iov_iter_init(&to, iov, nr_segs, len, 0); | ||
2849 | |||
2863 | INIT_LIST_HEAD(&rdata_list); | 2850 | INIT_LIST_HEAD(&rdata_list); |
2864 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 2851 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
2865 | open_file = file->private_data; | 2852 | open_file = file->private_data; |
@@ -2917,55 +2904,44 @@ error: | |||
2917 | if (!list_empty(&rdata_list)) | 2904 | if (!list_empty(&rdata_list)) |
2918 | rc = 0; | 2905 | rc = 0; |
2919 | 2906 | ||
2907 | len = iov_iter_count(&to); | ||
2920 | /* the loop below should proceed in the order of increasing offsets */ | 2908 | /* the loop below should proceed in the order of increasing offsets */ |
2921 | restart_loop: | ||
2922 | list_for_each_entry_safe(rdata, tmp, &rdata_list, list) { | 2909 | list_for_each_entry_safe(rdata, tmp, &rdata_list, list) { |
2910 | again: | ||
2923 | if (!rc) { | 2911 | if (!rc) { |
2924 | ssize_t copied; | ||
2925 | |||
2926 | /* FIXME: freezable sleep too? */ | 2912 | /* FIXME: freezable sleep too? */ |
2927 | rc = wait_for_completion_killable(&rdata->done); | 2913 | rc = wait_for_completion_killable(&rdata->done); |
2928 | if (rc) | 2914 | if (rc) |
2929 | rc = -EINTR; | 2915 | rc = -EINTR; |
2930 | else if (rdata->result) | 2916 | else if (rdata->result) { |
2931 | rc = rdata->result; | 2917 | rc = rdata->result; |
2932 | else { | 2918 | /* resend call if it's a retryable error */ |
2933 | rc = cifs_readdata_to_iov(rdata, iov, | 2919 | if (rc == -EAGAIN) { |
2934 | nr_segs, *poffset, | 2920 | rc = cifs_retry_async_readv(rdata); |
2935 | &copied); | 2921 | goto again; |
2936 | total_read += copied; | 2922 | } |
2923 | } else { | ||
2924 | rc = cifs_readdata_to_iov(rdata, &to); | ||
2937 | } | 2925 | } |
2938 | 2926 | ||
2939 | /* resend call if it's a retryable error */ | ||
2940 | if (rc == -EAGAIN) { | ||
2941 | rc = cifs_retry_async_readv(rdata); | ||
2942 | goto restart_loop; | ||
2943 | } | ||
2944 | } | 2927 | } |
2945 | list_del_init(&rdata->list); | 2928 | list_del_init(&rdata->list); |
2946 | kref_put(&rdata->refcount, cifs_uncached_readdata_release); | 2929 | kref_put(&rdata->refcount, cifs_uncached_readdata_release); |
2947 | } | 2930 | } |
2948 | 2931 | ||
2932 | total_read = len - iov_iter_count(&to); | ||
2933 | |||
2949 | cifs_stats_bytes_read(tcon, total_read); | 2934 | cifs_stats_bytes_read(tcon, total_read); |
2950 | *poffset += total_read; | ||
2951 | 2935 | ||
2952 | /* mask nodata case */ | 2936 | /* mask nodata case */ |
2953 | if (rc == -ENODATA) | 2937 | if (rc == -ENODATA) |
2954 | rc = 0; | 2938 | rc = 0; |
2955 | 2939 | ||
2956 | return total_read ? total_read : rc; | 2940 | if (total_read) { |
2957 | } | 2941 | iocb->ki_pos = pos + total_read; |
2958 | 2942 | return total_read; | |
2959 | ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, | 2943 | } |
2960 | unsigned long nr_segs, loff_t pos) | 2944 | return rc; |
2961 | { | ||
2962 | ssize_t read; | ||
2963 | |||
2964 | read = cifs_iovec_read(iocb->ki_filp, iov, nr_segs, &pos); | ||
2965 | if (read > 0) | ||
2966 | iocb->ki_pos = pos; | ||
2967 | |||
2968 | return read; | ||
2969 | } | 2945 | } |
2970 | 2946 | ||
2971 | ssize_t | 2947 | ssize_t |
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 3190ca973dd6..1e5b45359509 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c | |||
@@ -424,7 +424,7 @@ int dlm_lowcomms_addr(int nodeid, struct sockaddr_storage *addr, int len) | |||
424 | } | 424 | } |
425 | 425 | ||
426 | /* Data available on socket or listen socket received a connect */ | 426 | /* Data available on socket or listen socket received a connect */ |
427 | static void lowcomms_data_ready(struct sock *sk, int count_unused) | 427 | static void lowcomms_data_ready(struct sock *sk) |
428 | { | 428 | { |
429 | struct connection *con = sock2con(sk); | 429 | struct connection *con = sock2con(sk); |
430 | if (con && !test_and_set_bit(CF_READ_PENDING, &con->flags)) | 430 | if (con && !test_and_set_bit(CF_READ_PENDING, &con->flags)) |
@@ -813,7 +813,7 @@ EXPORT_SYMBOL(kernel_read); | |||
813 | 813 | ||
814 | ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len) | 814 | ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len) |
815 | { | 815 | { |
816 | ssize_t res = file->f_op->read(file, (void __user *)addr, len, &pos); | 816 | ssize_t res = vfs_read(file, (void __user *)addr, len, &pos); |
817 | if (res > 0) | 817 | if (res > 0) |
818 | flush_icache_range(addr, addr + len); | 818 | flush_icache_range(addr, addr + len); |
819 | return res; | 819 | return res; |
diff --git a/fs/exofs/ore_raid.c b/fs/exofs/ore_raid.c index 7682b970d0f1..4e2c032ab8a1 100644 --- a/fs/exofs/ore_raid.c +++ b/fs/exofs/ore_raid.c | |||
@@ -21,12 +21,12 @@ | |||
21 | #undef ORE_DBGMSG2 | 21 | #undef ORE_DBGMSG2 |
22 | #define ORE_DBGMSG2 ORE_DBGMSG | 22 | #define ORE_DBGMSG2 ORE_DBGMSG |
23 | 23 | ||
24 | struct page *_raid_page_alloc(void) | 24 | static struct page *_raid_page_alloc(void) |
25 | { | 25 | { |
26 | return alloc_page(GFP_KERNEL); | 26 | return alloc_page(GFP_KERNEL); |
27 | } | 27 | } |
28 | 28 | ||
29 | void _raid_page_free(struct page *p) | 29 | static void _raid_page_free(struct page *p) |
30 | { | 30 | { |
31 | __free_page(p); | 31 | __free_page(p); |
32 | } | 32 | } |
diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 9d9763328734..ed73ed8ebbee 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c | |||
@@ -543,7 +543,7 @@ static int exofs_devs_2_odi(struct exofs_dt_device_info *dt_dev, | |||
543 | return !(odi->systemid_len || odi->osdname_len); | 543 | return !(odi->systemid_len || odi->osdname_len); |
544 | } | 544 | } |
545 | 545 | ||
546 | int __alloc_dev_table(struct exofs_sb_info *sbi, unsigned numdevs, | 546 | static int __alloc_dev_table(struct exofs_sb_info *sbi, unsigned numdevs, |
547 | struct exofs_dev **peds) | 547 | struct exofs_dev **peds) |
548 | { | 548 | { |
549 | struct __alloc_ore_devs_and_exofs_devs { | 549 | struct __alloc_ore_devs_and_exofs_devs { |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 4e508fc83dcf..ca7502d89fde 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
@@ -146,7 +146,7 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov, | |||
146 | overwrite = 1; | 146 | overwrite = 1; |
147 | } | 147 | } |
148 | 148 | ||
149 | ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); | 149 | ret = __generic_file_aio_write(iocb, iov, nr_segs); |
150 | mutex_unlock(&inode->i_mutex); | 150 | mutex_unlock(&inode->i_mutex); |
151 | 151 | ||
152 | if (ret > 0) { | 152 | if (ret > 0) { |
@@ -25,7 +25,10 @@ | |||
25 | 25 | ||
26 | int sysctl_nr_open __read_mostly = 1024*1024; | 26 | int sysctl_nr_open __read_mostly = 1024*1024; |
27 | int sysctl_nr_open_min = BITS_PER_LONG; | 27 | int sysctl_nr_open_min = BITS_PER_LONG; |
28 | int sysctl_nr_open_max = 1024 * 1024; /* raised later */ | 28 | /* our max() is unusable in constant expressions ;-/ */ |
29 | #define __const_max(x, y) ((x) < (y) ? (x) : (y)) | ||
30 | int sysctl_nr_open_max = __const_max(INT_MAX, ~(size_t)0/sizeof(void *)) & | ||
31 | -BITS_PER_LONG; | ||
29 | 32 | ||
30 | static void *alloc_fdmem(size_t size) | 33 | static void *alloc_fdmem(size_t size) |
31 | { | 34 | { |
@@ -429,12 +432,6 @@ void exit_files(struct task_struct *tsk) | |||
429 | } | 432 | } |
430 | } | 433 | } |
431 | 434 | ||
432 | void __init files_defer_init(void) | ||
433 | { | ||
434 | sysctl_nr_open_max = min((size_t)INT_MAX, ~(size_t)0/sizeof(void *)) & | ||
435 | -BITS_PER_LONG; | ||
436 | } | ||
437 | |||
438 | struct files_struct init_files = { | 435 | struct files_struct init_files = { |
439 | .count = ATOMIC_INIT(1), | 436 | .count = ATOMIC_INIT(1), |
440 | .fdt = &init_files.fdtab, | 437 | .fdt = &init_files.fdtab, |
diff --git a/fs/file_table.c b/fs/file_table.c index 01071c4d752e..a374f5033e97 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -52,7 +52,6 @@ static void file_free_rcu(struct rcu_head *head) | |||
52 | static inline void file_free(struct file *f) | 52 | static inline void file_free(struct file *f) |
53 | { | 53 | { |
54 | percpu_counter_dec(&nr_files); | 54 | percpu_counter_dec(&nr_files); |
55 | file_check_state(f); | ||
56 | call_rcu(&f->f_u.fu_rcuhead, file_free_rcu); | 55 | call_rcu(&f->f_u.fu_rcuhead, file_free_rcu); |
57 | } | 56 | } |
58 | 57 | ||
@@ -178,47 +177,12 @@ struct file *alloc_file(struct path *path, fmode_t mode, | |||
178 | file->f_mapping = path->dentry->d_inode->i_mapping; | 177 | file->f_mapping = path->dentry->d_inode->i_mapping; |
179 | file->f_mode = mode; | 178 | file->f_mode = mode; |
180 | file->f_op = fop; | 179 | file->f_op = fop; |
181 | |||
182 | /* | ||
183 | * These mounts don't really matter in practice | ||
184 | * for r/o bind mounts. They aren't userspace- | ||
185 | * visible. We do this for consistency, and so | ||
186 | * that we can do debugging checks at __fput() | ||
187 | */ | ||
188 | if ((mode & FMODE_WRITE) && !special_file(path->dentry->d_inode->i_mode)) { | ||
189 | file_take_write(file); | ||
190 | WARN_ON(mnt_clone_write(path->mnt)); | ||
191 | } | ||
192 | if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | 180 | if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) |
193 | i_readcount_inc(path->dentry->d_inode); | 181 | i_readcount_inc(path->dentry->d_inode); |
194 | return file; | 182 | return file; |
195 | } | 183 | } |
196 | EXPORT_SYMBOL(alloc_file); | 184 | EXPORT_SYMBOL(alloc_file); |
197 | 185 | ||
198 | /** | ||
199 | * drop_file_write_access - give up ability to write to a file | ||
200 | * @file: the file to which we will stop writing | ||
201 | * | ||
202 | * This is a central place which will give up the ability | ||
203 | * to write to @file, along with access to write through | ||
204 | * its vfsmount. | ||
205 | */ | ||
206 | static void drop_file_write_access(struct file *file) | ||
207 | { | ||
208 | struct vfsmount *mnt = file->f_path.mnt; | ||
209 | struct dentry *dentry = file->f_path.dentry; | ||
210 | struct inode *inode = dentry->d_inode; | ||
211 | |||
212 | put_write_access(inode); | ||
213 | |||
214 | if (special_file(inode->i_mode)) | ||
215 | return; | ||
216 | if (file_check_writeable(file) != 0) | ||
217 | return; | ||
218 | __mnt_drop_write(mnt); | ||
219 | file_release_write(file); | ||
220 | } | ||
221 | |||
222 | /* the real guts of fput() - releasing the last reference to file | 186 | /* the real guts of fput() - releasing the last reference to file |
223 | */ | 187 | */ |
224 | static void __fput(struct file *file) | 188 | static void __fput(struct file *file) |
@@ -253,8 +217,10 @@ static void __fput(struct file *file) | |||
253 | put_pid(file->f_owner.pid); | 217 | put_pid(file->f_owner.pid); |
254 | if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | 218 | if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) |
255 | i_readcount_dec(inode); | 219 | i_readcount_dec(inode); |
256 | if (file->f_mode & FMODE_WRITE) | 220 | if (file->f_mode & FMODE_WRITER) { |
257 | drop_file_write_access(file); | 221 | put_write_access(inode); |
222 | __mnt_drop_write(mnt); | ||
223 | } | ||
258 | file->f_path.dentry = NULL; | 224 | file->f_path.dentry = NULL; |
259 | file->f_path.mnt = NULL; | 225 | file->f_path.mnt = NULL; |
260 | file->f_inode = NULL; | 226 | file->f_inode = NULL; |
@@ -359,6 +325,5 @@ void __init files_init(unsigned long mempages) | |||
359 | 325 | ||
360 | n = (mempages * (PAGE_SIZE / 1024)) / 10; | 326 | n = (mempages * (PAGE_SIZE / 1024)) / 10; |
361 | files_stat.max_files = max_t(unsigned long, n, NR_FILE); | 327 | files_stat.max_files = max_t(unsigned long, n, NR_FILE); |
362 | files_defer_init(); | ||
363 | percpu_counter_init(&nr_files, 0); | 328 | percpu_counter_init(&nr_files, 0); |
364 | } | 329 | } |
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 0a648bb455ae..aac71ce373e4 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -667,15 +667,15 @@ static void fuse_copy_finish(struct fuse_copy_state *cs) | |||
667 | struct pipe_buffer *buf = cs->currbuf; | 667 | struct pipe_buffer *buf = cs->currbuf; |
668 | 668 | ||
669 | if (!cs->write) { | 669 | if (!cs->write) { |
670 | buf->ops->unmap(cs->pipe, buf, cs->mapaddr); | 670 | kunmap_atomic(cs->mapaddr); |
671 | } else { | 671 | } else { |
672 | kunmap(buf->page); | 672 | kunmap_atomic(cs->mapaddr); |
673 | buf->len = PAGE_SIZE - cs->len; | 673 | buf->len = PAGE_SIZE - cs->len; |
674 | } | 674 | } |
675 | cs->currbuf = NULL; | 675 | cs->currbuf = NULL; |
676 | cs->mapaddr = NULL; | 676 | cs->mapaddr = NULL; |
677 | } else if (cs->mapaddr) { | 677 | } else if (cs->mapaddr) { |
678 | kunmap(cs->pg); | 678 | kunmap_atomic(cs->mapaddr); |
679 | if (cs->write) { | 679 | if (cs->write) { |
680 | flush_dcache_page(cs->pg); | 680 | flush_dcache_page(cs->pg); |
681 | set_page_dirty_lock(cs->pg); | 681 | set_page_dirty_lock(cs->pg); |
@@ -706,7 +706,7 @@ static int fuse_copy_fill(struct fuse_copy_state *cs) | |||
706 | 706 | ||
707 | BUG_ON(!cs->nr_segs); | 707 | BUG_ON(!cs->nr_segs); |
708 | cs->currbuf = buf; | 708 | cs->currbuf = buf; |
709 | cs->mapaddr = buf->ops->map(cs->pipe, buf, 0); | 709 | cs->mapaddr = kmap_atomic(buf->page); |
710 | cs->len = buf->len; | 710 | cs->len = buf->len; |
711 | cs->buf = cs->mapaddr + buf->offset; | 711 | cs->buf = cs->mapaddr + buf->offset; |
712 | cs->pipebufs++; | 712 | cs->pipebufs++; |
@@ -726,7 +726,7 @@ static int fuse_copy_fill(struct fuse_copy_state *cs) | |||
726 | buf->len = 0; | 726 | buf->len = 0; |
727 | 727 | ||
728 | cs->currbuf = buf; | 728 | cs->currbuf = buf; |
729 | cs->mapaddr = kmap(page); | 729 | cs->mapaddr = kmap_atomic(page); |
730 | cs->buf = cs->mapaddr; | 730 | cs->buf = cs->mapaddr; |
731 | cs->len = PAGE_SIZE; | 731 | cs->len = PAGE_SIZE; |
732 | cs->pipebufs++; | 732 | cs->pipebufs++; |
@@ -745,7 +745,7 @@ static int fuse_copy_fill(struct fuse_copy_state *cs) | |||
745 | return err; | 745 | return err; |
746 | BUG_ON(err != 1); | 746 | BUG_ON(err != 1); |
747 | offset = cs->addr % PAGE_SIZE; | 747 | offset = cs->addr % PAGE_SIZE; |
748 | cs->mapaddr = kmap(cs->pg); | 748 | cs->mapaddr = kmap_atomic(cs->pg); |
749 | cs->buf = cs->mapaddr + offset; | 749 | cs->buf = cs->mapaddr + offset; |
750 | cs->len = min(PAGE_SIZE - offset, cs->seglen); | 750 | cs->len = min(PAGE_SIZE - offset, cs->seglen); |
751 | cs->seglen -= cs->len; | 751 | cs->seglen -= cs->len; |
@@ -874,7 +874,7 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) | |||
874 | out_fallback_unlock: | 874 | out_fallback_unlock: |
875 | unlock_page(newpage); | 875 | unlock_page(newpage); |
876 | out_fallback: | 876 | out_fallback: |
877 | cs->mapaddr = buf->ops->map(cs->pipe, buf, 1); | 877 | cs->mapaddr = kmap_atomic(buf->page); |
878 | cs->buf = cs->mapaddr + buf->offset; | 878 | cs->buf = cs->mapaddr + buf->offset; |
879 | 879 | ||
880 | err = lock_request(cs->fc, cs->req); | 880 | err = lock_request(cs->fc, cs->req); |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 48992cac714b..13f8bdec5110 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -1086,9 +1086,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req, | |||
1086 | if (mapping_writably_mapped(mapping)) | 1086 | if (mapping_writably_mapped(mapping)) |
1087 | flush_dcache_page(page); | 1087 | flush_dcache_page(page); |
1088 | 1088 | ||
1089 | pagefault_disable(); | ||
1090 | tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes); | 1089 | tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes); |
1091 | pagefault_enable(); | ||
1092 | flush_dcache_page(page); | 1090 | flush_dcache_page(page); |
1093 | 1091 | ||
1094 | mark_page_accessed(page); | 1092 | mark_page_accessed(page); |
@@ -1237,8 +1235,7 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
1237 | goto out; | 1235 | goto out; |
1238 | 1236 | ||
1239 | if (file->f_flags & O_DIRECT) { | 1237 | if (file->f_flags & O_DIRECT) { |
1240 | written = generic_file_direct_write(iocb, iov, &nr_segs, | 1238 | written = generic_file_direct_write(iocb, iov, &nr_segs, pos, |
1241 | pos, &iocb->ki_pos, | ||
1242 | count, ocount); | 1239 | count, ocount); |
1243 | if (written < 0 || written == count) | 1240 | if (written < 0 || written == count) |
1244 | goto out; | 1241 | goto out; |
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 10d6c41aecad..6bf06a07f3e0 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c | |||
@@ -235,6 +235,7 @@ out_err: | |||
235 | if (warned++ == 0) | 235 | if (warned++ == 0) |
236 | printk(KERN_WARNING | 236 | printk(KERN_WARNING |
237 | "lockd_up: makesock failed, error=%d\n", err); | 237 | "lockd_up: makesock failed, error=%d\n", err); |
238 | svc_shutdown_net(serv, net); | ||
238 | return err; | 239 | return err; |
239 | } | 240 | } |
240 | 241 | ||
diff --git a/fs/mount.h b/fs/mount.h index b29e42f05f34..d55297f2fa05 100644 --- a/fs/mount.h +++ b/fs/mount.h | |||
@@ -10,7 +10,7 @@ struct mnt_namespace { | |||
10 | struct user_namespace *user_ns; | 10 | struct user_namespace *user_ns; |
11 | u64 seq; /* Sequence number to prevent loops */ | 11 | u64 seq; /* Sequence number to prevent loops */ |
12 | wait_queue_head_t poll; | 12 | wait_queue_head_t poll; |
13 | int event; | 13 | u64 event; |
14 | }; | 14 | }; |
15 | 15 | ||
16 | struct mnt_pcp { | 16 | struct mnt_pcp { |
@@ -104,6 +104,9 @@ struct proc_mounts { | |||
104 | struct mnt_namespace *ns; | 104 | struct mnt_namespace *ns; |
105 | struct path root; | 105 | struct path root; |
106 | int (*show)(struct seq_file *, struct vfsmount *); | 106 | int (*show)(struct seq_file *, struct vfsmount *); |
107 | void *cached_mount; | ||
108 | u64 cached_event; | ||
109 | loff_t cached_index; | ||
107 | }; | 110 | }; |
108 | 111 | ||
109 | #define proc_mounts(p) (container_of((p), struct proc_mounts, m)) | 112 | #define proc_mounts(p) (container_of((p), struct proc_mounts, m)) |
diff --git a/fs/namei.c b/fs/namei.c index 88339f59efb5..c6157c894fce 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -358,6 +358,7 @@ int generic_permission(struct inode *inode, int mask) | |||
358 | 358 | ||
359 | return -EACCES; | 359 | return -EACCES; |
360 | } | 360 | } |
361 | EXPORT_SYMBOL(generic_permission); | ||
361 | 362 | ||
362 | /* | 363 | /* |
363 | * We _really_ want to just do "generic_permission()" without | 364 | * We _really_ want to just do "generic_permission()" without |
@@ -455,6 +456,7 @@ int inode_permission(struct inode *inode, int mask) | |||
455 | return retval; | 456 | return retval; |
456 | return __inode_permission(inode, mask); | 457 | return __inode_permission(inode, mask); |
457 | } | 458 | } |
459 | EXPORT_SYMBOL(inode_permission); | ||
458 | 460 | ||
459 | /** | 461 | /** |
460 | * path_get - get a reference to a path | 462 | * path_get - get a reference to a path |
@@ -924,6 +926,7 @@ int follow_up(struct path *path) | |||
924 | path->mnt = &parent->mnt; | 926 | path->mnt = &parent->mnt; |
925 | return 1; | 927 | return 1; |
926 | } | 928 | } |
929 | EXPORT_SYMBOL(follow_up); | ||
927 | 930 | ||
928 | /* | 931 | /* |
929 | * Perform an automount | 932 | * Perform an automount |
@@ -1085,6 +1088,7 @@ int follow_down_one(struct path *path) | |||
1085 | } | 1088 | } |
1086 | return 0; | 1089 | return 0; |
1087 | } | 1090 | } |
1091 | EXPORT_SYMBOL(follow_down_one); | ||
1088 | 1092 | ||
1089 | static inline bool managed_dentry_might_block(struct dentry *dentry) | 1093 | static inline bool managed_dentry_might_block(struct dentry *dentry) |
1090 | { | 1094 | { |
@@ -1223,6 +1227,7 @@ int follow_down(struct path *path) | |||
1223 | } | 1227 | } |
1224 | return 0; | 1228 | return 0; |
1225 | } | 1229 | } |
1230 | EXPORT_SYMBOL(follow_down); | ||
1226 | 1231 | ||
1227 | /* | 1232 | /* |
1228 | * Skip to top of mountpoint pile in refwalk mode for follow_dotdot() | 1233 | * Skip to top of mountpoint pile in refwalk mode for follow_dotdot() |
@@ -2025,6 +2030,7 @@ int kern_path(const char *name, unsigned int flags, struct path *path) | |||
2025 | *path = nd.path; | 2030 | *path = nd.path; |
2026 | return res; | 2031 | return res; |
2027 | } | 2032 | } |
2033 | EXPORT_SYMBOL(kern_path); | ||
2028 | 2034 | ||
2029 | /** | 2035 | /** |
2030 | * vfs_path_lookup - lookup a file path relative to a dentry-vfsmount pair | 2036 | * vfs_path_lookup - lookup a file path relative to a dentry-vfsmount pair |
@@ -2049,6 +2055,7 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt, | |||
2049 | *path = nd.path; | 2055 | *path = nd.path; |
2050 | return err; | 2056 | return err; |
2051 | } | 2057 | } |
2058 | EXPORT_SYMBOL(vfs_path_lookup); | ||
2052 | 2059 | ||
2053 | /* | 2060 | /* |
2054 | * Restricted form of lookup. Doesn't follow links, single-component only, | 2061 | * Restricted form of lookup. Doesn't follow links, single-component only, |
@@ -2111,6 +2118,7 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) | |||
2111 | 2118 | ||
2112 | return __lookup_hash(&this, base, 0); | 2119 | return __lookup_hash(&this, base, 0); |
2113 | } | 2120 | } |
2121 | EXPORT_SYMBOL(lookup_one_len); | ||
2114 | 2122 | ||
2115 | int user_path_at_empty(int dfd, const char __user *name, unsigned flags, | 2123 | int user_path_at_empty(int dfd, const char __user *name, unsigned flags, |
2116 | struct path *path, int *empty) | 2124 | struct path *path, int *empty) |
@@ -2135,6 +2143,7 @@ int user_path_at(int dfd, const char __user *name, unsigned flags, | |||
2135 | { | 2143 | { |
2136 | return user_path_at_empty(dfd, name, flags, path, NULL); | 2144 | return user_path_at_empty(dfd, name, flags, path, NULL); |
2137 | } | 2145 | } |
2146 | EXPORT_SYMBOL(user_path_at); | ||
2138 | 2147 | ||
2139 | /* | 2148 | /* |
2140 | * NB: most callers don't do anything directly with the reference to the | 2149 | * NB: most callers don't do anything directly with the reference to the |
@@ -2477,6 +2486,7 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2) | |||
2477 | mutex_lock_nested(&p2->d_inode->i_mutex, I_MUTEX_CHILD); | 2486 | mutex_lock_nested(&p2->d_inode->i_mutex, I_MUTEX_CHILD); |
2478 | return NULL; | 2487 | return NULL; |
2479 | } | 2488 | } |
2489 | EXPORT_SYMBOL(lock_rename); | ||
2480 | 2490 | ||
2481 | void unlock_rename(struct dentry *p1, struct dentry *p2) | 2491 | void unlock_rename(struct dentry *p1, struct dentry *p2) |
2482 | { | 2492 | { |
@@ -2486,6 +2496,7 @@ void unlock_rename(struct dentry *p1, struct dentry *p2) | |||
2486 | mutex_unlock(&p1->d_inode->i_sb->s_vfs_rename_mutex); | 2496 | mutex_unlock(&p1->d_inode->i_sb->s_vfs_rename_mutex); |
2487 | } | 2497 | } |
2488 | } | 2498 | } |
2499 | EXPORT_SYMBOL(unlock_rename); | ||
2489 | 2500 | ||
2490 | int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 2501 | int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
2491 | bool want_excl) | 2502 | bool want_excl) |
@@ -2506,6 +2517,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
2506 | fsnotify_create(dir, dentry); | 2517 | fsnotify_create(dir, dentry); |
2507 | return error; | 2518 | return error; |
2508 | } | 2519 | } |
2520 | EXPORT_SYMBOL(vfs_create); | ||
2509 | 2521 | ||
2510 | static int may_open(struct path *path, int acc_mode, int flag) | 2522 | static int may_open(struct path *path, int acc_mode, int flag) |
2511 | { | 2523 | { |
@@ -3375,6 +3387,7 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) | |||
3375 | fsnotify_create(dir, dentry); | 3387 | fsnotify_create(dir, dentry); |
3376 | return error; | 3388 | return error; |
3377 | } | 3389 | } |
3390 | EXPORT_SYMBOL(vfs_mknod); | ||
3378 | 3391 | ||
3379 | static int may_mknod(umode_t mode) | 3392 | static int may_mknod(umode_t mode) |
3380 | { | 3393 | { |
@@ -3464,6 +3477,7 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
3464 | fsnotify_mkdir(dir, dentry); | 3477 | fsnotify_mkdir(dir, dentry); |
3465 | return error; | 3478 | return error; |
3466 | } | 3479 | } |
3480 | EXPORT_SYMBOL(vfs_mkdir); | ||
3467 | 3481 | ||
3468 | SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode) | 3482 | SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode) |
3469 | { | 3483 | { |
@@ -3518,6 +3532,7 @@ void dentry_unhash(struct dentry *dentry) | |||
3518 | __d_drop(dentry); | 3532 | __d_drop(dentry); |
3519 | spin_unlock(&dentry->d_lock); | 3533 | spin_unlock(&dentry->d_lock); |
3520 | } | 3534 | } |
3535 | EXPORT_SYMBOL(dentry_unhash); | ||
3521 | 3536 | ||
3522 | int vfs_rmdir(struct inode *dir, struct dentry *dentry) | 3537 | int vfs_rmdir(struct inode *dir, struct dentry *dentry) |
3523 | { | 3538 | { |
@@ -3555,6 +3570,7 @@ out: | |||
3555 | d_delete(dentry); | 3570 | d_delete(dentry); |
3556 | return error; | 3571 | return error; |
3557 | } | 3572 | } |
3573 | EXPORT_SYMBOL(vfs_rmdir); | ||
3558 | 3574 | ||
3559 | static long do_rmdir(int dfd, const char __user *pathname) | 3575 | static long do_rmdir(int dfd, const char __user *pathname) |
3560 | { | 3576 | { |
@@ -3672,6 +3688,7 @@ out: | |||
3672 | 3688 | ||
3673 | return error; | 3689 | return error; |
3674 | } | 3690 | } |
3691 | EXPORT_SYMBOL(vfs_unlink); | ||
3675 | 3692 | ||
3676 | /* | 3693 | /* |
3677 | * Make sure that the actual truncation of the file will occur outside its | 3694 | * Make sure that the actual truncation of the file will occur outside its |
@@ -3785,6 +3802,7 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname) | |||
3785 | fsnotify_create(dir, dentry); | 3802 | fsnotify_create(dir, dentry); |
3786 | return error; | 3803 | return error; |
3787 | } | 3804 | } |
3805 | EXPORT_SYMBOL(vfs_symlink); | ||
3788 | 3806 | ||
3789 | SYSCALL_DEFINE3(symlinkat, const char __user *, oldname, | 3807 | SYSCALL_DEFINE3(symlinkat, const char __user *, oldname, |
3790 | int, newdfd, const char __user *, newname) | 3808 | int, newdfd, const char __user *, newname) |
@@ -3893,6 +3911,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de | |||
3893 | fsnotify_link(dir, inode, new_dentry); | 3911 | fsnotify_link(dir, inode, new_dentry); |
3894 | return error; | 3912 | return error; |
3895 | } | 3913 | } |
3914 | EXPORT_SYMBOL(vfs_link); | ||
3896 | 3915 | ||
3897 | /* | 3916 | /* |
3898 | * Hardlinks are often used in delicate situations. We avoid | 3917 | * Hardlinks are often used in delicate situations. We avoid |
@@ -4152,6 +4171,7 @@ out: | |||
4152 | 4171 | ||
4153 | return error; | 4172 | return error; |
4154 | } | 4173 | } |
4174 | EXPORT_SYMBOL(vfs_rename); | ||
4155 | 4175 | ||
4156 | SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname, | 4176 | SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname, |
4157 | int, newdfd, const char __user *, newname, unsigned int, flags) | 4177 | int, newdfd, const char __user *, newname, unsigned int, flags) |
@@ -4304,11 +4324,9 @@ SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newna | |||
4304 | return sys_renameat2(AT_FDCWD, oldname, AT_FDCWD, newname, 0); | 4324 | return sys_renameat2(AT_FDCWD, oldname, AT_FDCWD, newname, 0); |
4305 | } | 4325 | } |
4306 | 4326 | ||
4307 | int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link) | 4327 | int readlink_copy(char __user *buffer, int buflen, const char *link) |
4308 | { | 4328 | { |
4309 | int len; | 4329 | int len = PTR_ERR(link); |
4310 | |||
4311 | len = PTR_ERR(link); | ||
4312 | if (IS_ERR(link)) | 4330 | if (IS_ERR(link)) |
4313 | goto out; | 4331 | goto out; |
4314 | 4332 | ||
@@ -4320,6 +4338,7 @@ int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const c | |||
4320 | out: | 4338 | out: |
4321 | return len; | 4339 | return len; |
4322 | } | 4340 | } |
4341 | EXPORT_SYMBOL(readlink_copy); | ||
4323 | 4342 | ||
4324 | /* | 4343 | /* |
4325 | * A helper for ->readlink(). This should be used *ONLY* for symlinks that | 4344 | * A helper for ->readlink(). This should be used *ONLY* for symlinks that |
@@ -4337,11 +4356,12 @@ int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen) | |||
4337 | if (IS_ERR(cookie)) | 4356 | if (IS_ERR(cookie)) |
4338 | return PTR_ERR(cookie); | 4357 | return PTR_ERR(cookie); |
4339 | 4358 | ||
4340 | res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd)); | 4359 | res = readlink_copy(buffer, buflen, nd_get_link(&nd)); |
4341 | if (dentry->d_inode->i_op->put_link) | 4360 | if (dentry->d_inode->i_op->put_link) |
4342 | dentry->d_inode->i_op->put_link(dentry, &nd, cookie); | 4361 | dentry->d_inode->i_op->put_link(dentry, &nd, cookie); |
4343 | return res; | 4362 | return res; |
4344 | } | 4363 | } |
4364 | EXPORT_SYMBOL(generic_readlink); | ||
4345 | 4365 | ||
4346 | /* get the link contents into pagecache */ | 4366 | /* get the link contents into pagecache */ |
4347 | static char *page_getlink(struct dentry * dentry, struct page **ppage) | 4367 | static char *page_getlink(struct dentry * dentry, struct page **ppage) |
@@ -4361,14 +4381,14 @@ static char *page_getlink(struct dentry * dentry, struct page **ppage) | |||
4361 | int page_readlink(struct dentry *dentry, char __user *buffer, int buflen) | 4381 | int page_readlink(struct dentry *dentry, char __user *buffer, int buflen) |
4362 | { | 4382 | { |
4363 | struct page *page = NULL; | 4383 | struct page *page = NULL; |
4364 | char *s = page_getlink(dentry, &page); | 4384 | int res = readlink_copy(buffer, buflen, page_getlink(dentry, &page)); |
4365 | int res = vfs_readlink(dentry,buffer,buflen,s); | ||
4366 | if (page) { | 4385 | if (page) { |
4367 | kunmap(page); | 4386 | kunmap(page); |
4368 | page_cache_release(page); | 4387 | page_cache_release(page); |
4369 | } | 4388 | } |
4370 | return res; | 4389 | return res; |
4371 | } | 4390 | } |
4391 | EXPORT_SYMBOL(page_readlink); | ||
4372 | 4392 | ||
4373 | void *page_follow_link_light(struct dentry *dentry, struct nameidata *nd) | 4393 | void *page_follow_link_light(struct dentry *dentry, struct nameidata *nd) |
4374 | { | 4394 | { |
@@ -4376,6 +4396,7 @@ void *page_follow_link_light(struct dentry *dentry, struct nameidata *nd) | |||
4376 | nd_set_link(nd, page_getlink(dentry, &page)); | 4396 | nd_set_link(nd, page_getlink(dentry, &page)); |
4377 | return page; | 4397 | return page; |
4378 | } | 4398 | } |
4399 | EXPORT_SYMBOL(page_follow_link_light); | ||
4379 | 4400 | ||
4380 | void page_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) | 4401 | void page_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) |
4381 | { | 4402 | { |
@@ -4386,6 +4407,7 @@ void page_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) | |||
4386 | page_cache_release(page); | 4407 | page_cache_release(page); |
4387 | } | 4408 | } |
4388 | } | 4409 | } |
4410 | EXPORT_SYMBOL(page_put_link); | ||
4389 | 4411 | ||
4390 | /* | 4412 | /* |
4391 | * The nofs argument instructs pagecache_write_begin to pass AOP_FLAG_NOFS | 4413 | * The nofs argument instructs pagecache_write_begin to pass AOP_FLAG_NOFS |
@@ -4423,45 +4445,18 @@ retry: | |||
4423 | fail: | 4445 | fail: |
4424 | return err; | 4446 | return err; |
4425 | } | 4447 | } |
4448 | EXPORT_SYMBOL(__page_symlink); | ||
4426 | 4449 | ||
4427 | int page_symlink(struct inode *inode, const char *symname, int len) | 4450 | int page_symlink(struct inode *inode, const char *symname, int len) |
4428 | { | 4451 | { |
4429 | return __page_symlink(inode, symname, len, | 4452 | return __page_symlink(inode, symname, len, |
4430 | !(mapping_gfp_mask(inode->i_mapping) & __GFP_FS)); | 4453 | !(mapping_gfp_mask(inode->i_mapping) & __GFP_FS)); |
4431 | } | 4454 | } |
4455 | EXPORT_SYMBOL(page_symlink); | ||
4432 | 4456 | ||
4433 | const struct inode_operations page_symlink_inode_operations = { | 4457 | const struct inode_operations page_symlink_inode_operations = { |
4434 | .readlink = generic_readlink, | 4458 | .readlink = generic_readlink, |
4435 | .follow_link = page_follow_link_light, | 4459 | .follow_link = page_follow_link_light, |
4436 | .put_link = page_put_link, | 4460 | .put_link = page_put_link, |
4437 | }; | 4461 | }; |
4438 | |||
4439 | EXPORT_SYMBOL(user_path_at); | ||
4440 | EXPORT_SYMBOL(follow_down_one); | ||
4441 | EXPORT_SYMBOL(follow_down); | ||
4442 | EXPORT_SYMBOL(follow_up); | ||
4443 | EXPORT_SYMBOL(get_write_access); /* nfsd */ | ||
4444 | EXPORT_SYMBOL(lock_rename); | ||
4445 | EXPORT_SYMBOL(lookup_one_len); | ||
4446 | EXPORT_SYMBOL(page_follow_link_light); | ||
4447 | EXPORT_SYMBOL(page_put_link); | ||
4448 | EXPORT_SYMBOL(page_readlink); | ||
4449 | EXPORT_SYMBOL(__page_symlink); | ||
4450 | EXPORT_SYMBOL(page_symlink); | ||
4451 | EXPORT_SYMBOL(page_symlink_inode_operations); | 4462 | EXPORT_SYMBOL(page_symlink_inode_operations); |
4452 | EXPORT_SYMBOL(kern_path); | ||
4453 | EXPORT_SYMBOL(vfs_path_lookup); | ||
4454 | EXPORT_SYMBOL(inode_permission); | ||
4455 | EXPORT_SYMBOL(unlock_rename); | ||
4456 | EXPORT_SYMBOL(vfs_create); | ||
4457 | EXPORT_SYMBOL(vfs_link); | ||
4458 | EXPORT_SYMBOL(vfs_mkdir); | ||
4459 | EXPORT_SYMBOL(vfs_mknod); | ||
4460 | EXPORT_SYMBOL(generic_permission); | ||
4461 | EXPORT_SYMBOL(vfs_readlink); | ||
4462 | EXPORT_SYMBOL(vfs_rename); | ||
4463 | EXPORT_SYMBOL(vfs_rmdir); | ||
4464 | EXPORT_SYMBOL(vfs_symlink); | ||
4465 | EXPORT_SYMBOL(vfs_unlink); | ||
4466 | EXPORT_SYMBOL(dentry_unhash); | ||
4467 | EXPORT_SYMBOL(generic_readlink); | ||
diff --git a/fs/namespace.c b/fs/namespace.c index 2ffc5a2905d4..182bc41cd887 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -52,7 +52,7 @@ static int __init set_mphash_entries(char *str) | |||
52 | } | 52 | } |
53 | __setup("mphash_entries=", set_mphash_entries); | 53 | __setup("mphash_entries=", set_mphash_entries); |
54 | 54 | ||
55 | static int event; | 55 | static u64 event; |
56 | static DEFINE_IDA(mnt_id_ida); | 56 | static DEFINE_IDA(mnt_id_ida); |
57 | static DEFINE_IDA(mnt_group_ida); | 57 | static DEFINE_IDA(mnt_group_ida); |
58 | static DEFINE_SPINLOCK(mnt_id_lock); | 58 | static DEFINE_SPINLOCK(mnt_id_lock); |
@@ -414,9 +414,7 @@ EXPORT_SYMBOL_GPL(mnt_clone_write); | |||
414 | */ | 414 | */ |
415 | int __mnt_want_write_file(struct file *file) | 415 | int __mnt_want_write_file(struct file *file) |
416 | { | 416 | { |
417 | struct inode *inode = file_inode(file); | 417 | if (!(file->f_mode & FMODE_WRITER)) |
418 | |||
419 | if (!(file->f_mode & FMODE_WRITE) || special_file(inode->i_mode)) | ||
420 | return __mnt_want_write(file->f_path.mnt); | 418 | return __mnt_want_write(file->f_path.mnt); |
421 | else | 419 | else |
422 | return mnt_clone_write(file->f_path.mnt); | 420 | return mnt_clone_write(file->f_path.mnt); |
@@ -570,13 +568,17 @@ int sb_prepare_remount_readonly(struct super_block *sb) | |||
570 | static void free_vfsmnt(struct mount *mnt) | 568 | static void free_vfsmnt(struct mount *mnt) |
571 | { | 569 | { |
572 | kfree(mnt->mnt_devname); | 570 | kfree(mnt->mnt_devname); |
573 | mnt_free_id(mnt); | ||
574 | #ifdef CONFIG_SMP | 571 | #ifdef CONFIG_SMP |
575 | free_percpu(mnt->mnt_pcp); | 572 | free_percpu(mnt->mnt_pcp); |
576 | #endif | 573 | #endif |
577 | kmem_cache_free(mnt_cache, mnt); | 574 | kmem_cache_free(mnt_cache, mnt); |
578 | } | 575 | } |
579 | 576 | ||
577 | static void delayed_free_vfsmnt(struct rcu_head *head) | ||
578 | { | ||
579 | free_vfsmnt(container_of(head, struct mount, mnt_rcu)); | ||
580 | } | ||
581 | |||
580 | /* call under rcu_read_lock */ | 582 | /* call under rcu_read_lock */ |
581 | bool legitimize_mnt(struct vfsmount *bastard, unsigned seq) | 583 | bool legitimize_mnt(struct vfsmount *bastard, unsigned seq) |
582 | { | 584 | { |
@@ -848,6 +850,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void | |||
848 | 850 | ||
849 | root = mount_fs(type, flags, name, data); | 851 | root = mount_fs(type, flags, name, data); |
850 | if (IS_ERR(root)) { | 852 | if (IS_ERR(root)) { |
853 | mnt_free_id(mnt); | ||
851 | free_vfsmnt(mnt); | 854 | free_vfsmnt(mnt); |
852 | return ERR_CAST(root); | 855 | return ERR_CAST(root); |
853 | } | 856 | } |
@@ -885,7 +888,7 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, | |||
885 | goto out_free; | 888 | goto out_free; |
886 | } | 889 | } |
887 | 890 | ||
888 | mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~MNT_WRITE_HOLD; | 891 | mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~(MNT_WRITE_HOLD|MNT_MARKED); |
889 | /* Don't allow unprivileged users to change mount flags */ | 892 | /* Don't allow unprivileged users to change mount flags */ |
890 | if ((flag & CL_UNPRIVILEGED) && (mnt->mnt.mnt_flags & MNT_READONLY)) | 893 | if ((flag & CL_UNPRIVILEGED) && (mnt->mnt.mnt_flags & MNT_READONLY)) |
891 | mnt->mnt.mnt_flags |= MNT_LOCK_READONLY; | 894 | mnt->mnt.mnt_flags |= MNT_LOCK_READONLY; |
@@ -928,20 +931,11 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, | |||
928 | return mnt; | 931 | return mnt; |
929 | 932 | ||
930 | out_free: | 933 | out_free: |
934 | mnt_free_id(mnt); | ||
931 | free_vfsmnt(mnt); | 935 | free_vfsmnt(mnt); |
932 | return ERR_PTR(err); | 936 | return ERR_PTR(err); |
933 | } | 937 | } |
934 | 938 | ||
935 | static void delayed_free(struct rcu_head *head) | ||
936 | { | ||
937 | struct mount *mnt = container_of(head, struct mount, mnt_rcu); | ||
938 | kfree(mnt->mnt_devname); | ||
939 | #ifdef CONFIG_SMP | ||
940 | free_percpu(mnt->mnt_pcp); | ||
941 | #endif | ||
942 | kmem_cache_free(mnt_cache, mnt); | ||
943 | } | ||
944 | |||
945 | static void mntput_no_expire(struct mount *mnt) | 939 | static void mntput_no_expire(struct mount *mnt) |
946 | { | 940 | { |
947 | put_again: | 941 | put_again: |
@@ -991,7 +985,7 @@ put_again: | |||
991 | dput(mnt->mnt.mnt_root); | 985 | dput(mnt->mnt.mnt_root); |
992 | deactivate_super(mnt->mnt.mnt_sb); | 986 | deactivate_super(mnt->mnt.mnt_sb); |
993 | mnt_free_id(mnt); | 987 | mnt_free_id(mnt); |
994 | call_rcu(&mnt->mnt_rcu, delayed_free); | 988 | call_rcu(&mnt->mnt_rcu, delayed_free_vfsmnt); |
995 | } | 989 | } |
996 | 990 | ||
997 | void mntput(struct vfsmount *mnt) | 991 | void mntput(struct vfsmount *mnt) |
@@ -1100,14 +1094,29 @@ static void *m_start(struct seq_file *m, loff_t *pos) | |||
1100 | struct proc_mounts *p = proc_mounts(m); | 1094 | struct proc_mounts *p = proc_mounts(m); |
1101 | 1095 | ||
1102 | down_read(&namespace_sem); | 1096 | down_read(&namespace_sem); |
1103 | return seq_list_start(&p->ns->list, *pos); | 1097 | if (p->cached_event == p->ns->event) { |
1098 | void *v = p->cached_mount; | ||
1099 | if (*pos == p->cached_index) | ||
1100 | return v; | ||
1101 | if (*pos == p->cached_index + 1) { | ||
1102 | v = seq_list_next(v, &p->ns->list, &p->cached_index); | ||
1103 | return p->cached_mount = v; | ||
1104 | } | ||
1105 | } | ||
1106 | |||
1107 | p->cached_event = p->ns->event; | ||
1108 | p->cached_mount = seq_list_start(&p->ns->list, *pos); | ||
1109 | p->cached_index = *pos; | ||
1110 | return p->cached_mount; | ||
1104 | } | 1111 | } |
1105 | 1112 | ||
1106 | static void *m_next(struct seq_file *m, void *v, loff_t *pos) | 1113 | static void *m_next(struct seq_file *m, void *v, loff_t *pos) |
1107 | { | 1114 | { |
1108 | struct proc_mounts *p = proc_mounts(m); | 1115 | struct proc_mounts *p = proc_mounts(m); |
1109 | 1116 | ||
1110 | return seq_list_next(v, &p->ns->list, pos); | 1117 | p->cached_mount = seq_list_next(v, &p->ns->list, pos); |
1118 | p->cached_index = *pos; | ||
1119 | return p->cached_mount; | ||
1111 | } | 1120 | } |
1112 | 1121 | ||
1113 | static void m_stop(struct seq_file *m, void *v) | 1122 | static void m_stop(struct seq_file *m, void *v) |
@@ -1661,9 +1670,9 @@ static int attach_recursive_mnt(struct mount *source_mnt, | |||
1661 | if (err) | 1670 | if (err) |
1662 | goto out; | 1671 | goto out; |
1663 | err = propagate_mnt(dest_mnt, dest_mp, source_mnt, &tree_list); | 1672 | err = propagate_mnt(dest_mnt, dest_mp, source_mnt, &tree_list); |
1673 | lock_mount_hash(); | ||
1664 | if (err) | 1674 | if (err) |
1665 | goto out_cleanup_ids; | 1675 | goto out_cleanup_ids; |
1666 | lock_mount_hash(); | ||
1667 | for (p = source_mnt; p; p = next_mnt(p, source_mnt)) | 1676 | for (p = source_mnt; p; p = next_mnt(p, source_mnt)) |
1668 | set_mnt_shared(p); | 1677 | set_mnt_shared(p); |
1669 | } else { | 1678 | } else { |
@@ -1690,6 +1699,11 @@ static int attach_recursive_mnt(struct mount *source_mnt, | |||
1690 | return 0; | 1699 | return 0; |
1691 | 1700 | ||
1692 | out_cleanup_ids: | 1701 | out_cleanup_ids: |
1702 | while (!hlist_empty(&tree_list)) { | ||
1703 | child = hlist_entry(tree_list.first, struct mount, mnt_hash); | ||
1704 | umount_tree(child, 0); | ||
1705 | } | ||
1706 | unlock_mount_hash(); | ||
1693 | cleanup_group_ids(source_mnt, NULL); | 1707 | cleanup_group_ids(source_mnt, NULL); |
1694 | out: | 1708 | out: |
1695 | return err; | 1709 | return err; |
@@ -2044,7 +2058,7 @@ static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags) | |||
2044 | struct mount *parent; | 2058 | struct mount *parent; |
2045 | int err; | 2059 | int err; |
2046 | 2060 | ||
2047 | mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL | MNT_DOOMED | MNT_SYNC_UMOUNT); | 2061 | mnt_flags &= ~MNT_INTERNAL_FLAGS; |
2048 | 2062 | ||
2049 | mp = lock_mount(path); | 2063 | mp = lock_mount(path); |
2050 | if (IS_ERR(mp)) | 2064 | if (IS_ERR(mp)) |
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index c320ac52353e..08b8ea8c353e 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c | |||
@@ -339,7 +339,7 @@ ncp_lookup_validate(struct dentry *dentry, unsigned int flags) | |||
339 | if (val) | 339 | if (val) |
340 | goto finished; | 340 | goto finished; |
341 | 341 | ||
342 | DDPRINTK("ncp_lookup_validate: %pd2 not valid, age=%ld, server lookup\n", | 342 | ncp_dbg(2, "%pd2 not valid, age=%ld, server lookup\n", |
343 | dentry, NCP_GET_AGE(dentry)); | 343 | dentry, NCP_GET_AGE(dentry)); |
344 | 344 | ||
345 | len = sizeof(__name); | 345 | len = sizeof(__name); |
@@ -358,7 +358,7 @@ ncp_lookup_validate(struct dentry *dentry, unsigned int flags) | |||
358 | res = ncp_obtain_info(server, dir, __name, &(finfo.i)); | 358 | res = ncp_obtain_info(server, dir, __name, &(finfo.i)); |
359 | } | 359 | } |
360 | finfo.volume = finfo.i.volNumber; | 360 | finfo.volume = finfo.i.volNumber; |
361 | DDPRINTK("ncp_lookup_validate: looked for %pd/%s, res=%d\n", | 361 | ncp_dbg(2, "looked for %pd/%s, res=%d\n", |
362 | dentry->d_parent, __name, res); | 362 | dentry->d_parent, __name, res); |
363 | /* | 363 | /* |
364 | * If we didn't find it, or if it has a different dirEntNum to | 364 | * If we didn't find it, or if it has a different dirEntNum to |
@@ -372,14 +372,14 @@ ncp_lookup_validate(struct dentry *dentry, unsigned int flags) | |||
372 | ncp_new_dentry(dentry); | 372 | ncp_new_dentry(dentry); |
373 | val=1; | 373 | val=1; |
374 | } else | 374 | } else |
375 | DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n"); | 375 | ncp_dbg(2, "found, but dirEntNum changed\n"); |
376 | 376 | ||
377 | ncp_update_inode2(inode, &finfo); | 377 | ncp_update_inode2(inode, &finfo); |
378 | mutex_unlock(&inode->i_mutex); | 378 | mutex_unlock(&inode->i_mutex); |
379 | } | 379 | } |
380 | 380 | ||
381 | finished: | 381 | finished: |
382 | DDPRINTK("ncp_lookup_validate: result=%d\n", val); | 382 | ncp_dbg(2, "result=%d\n", val); |
383 | dput(parent); | 383 | dput(parent); |
384 | return val; | 384 | return val; |
385 | } | 385 | } |
@@ -453,8 +453,7 @@ static int ncp_readdir(struct file *file, struct dir_context *ctx) | |||
453 | ctl.page = NULL; | 453 | ctl.page = NULL; |
454 | ctl.cache = NULL; | 454 | ctl.cache = NULL; |
455 | 455 | ||
456 | DDPRINTK("ncp_readdir: reading %pD2, pos=%d\n", file, | 456 | ncp_dbg(2, "reading %pD2, pos=%d\n", file, (int)ctx->pos); |
457 | (int) ctx->pos); | ||
458 | 457 | ||
459 | result = -EIO; | 458 | result = -EIO; |
460 | /* Do not generate '.' and '..' when server is dead. */ | 459 | /* Do not generate '.' and '..' when server is dead. */ |
@@ -697,8 +696,7 @@ ncp_read_volume_list(struct file *file, struct dir_context *ctx, | |||
697 | struct ncp_entry_info entry; | 696 | struct ncp_entry_info entry; |
698 | int i; | 697 | int i; |
699 | 698 | ||
700 | DPRINTK("ncp_read_volume_list: pos=%ld\n", | 699 | ncp_dbg(1, "pos=%ld\n", (unsigned long)ctx->pos); |
701 | (unsigned long) ctx->pos); | ||
702 | 700 | ||
703 | for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) { | 701 | for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) { |
704 | int inval_dentry; | 702 | int inval_dentry; |
@@ -708,12 +706,11 @@ ncp_read_volume_list(struct file *file, struct dir_context *ctx, | |||
708 | if (!strlen(info.volume_name)) | 706 | if (!strlen(info.volume_name)) |
709 | continue; | 707 | continue; |
710 | 708 | ||
711 | DPRINTK("ncp_read_volume_list: found vol: %s\n", | 709 | ncp_dbg(1, "found vol: %s\n", info.volume_name); |
712 | info.volume_name); | ||
713 | 710 | ||
714 | if (ncp_lookup_volume(server, info.volume_name, | 711 | if (ncp_lookup_volume(server, info.volume_name, |
715 | &entry.i)) { | 712 | &entry.i)) { |
716 | DPRINTK("ncpfs: could not lookup vol %s\n", | 713 | ncp_dbg(1, "could not lookup vol %s\n", |
717 | info.volume_name); | 714 | info.volume_name); |
718 | continue; | 715 | continue; |
719 | } | 716 | } |
@@ -738,14 +735,13 @@ ncp_do_readdir(struct file *file, struct dir_context *ctx, | |||
738 | int more; | 735 | int more; |
739 | size_t bufsize; | 736 | size_t bufsize; |
740 | 737 | ||
741 | DPRINTK("ncp_do_readdir: %pD2, fpos=%ld\n", file, | 738 | ncp_dbg(1, "%pD2, fpos=%ld\n", file, (unsigned long)ctx->pos); |
742 | (unsigned long) ctx->pos); | 739 | ncp_vdbg("init %pD, volnum=%d, dirent=%u\n", |
743 | PPRINTK("ncp_do_readdir: init %pD, volnum=%d, dirent=%u\n", | 740 | file, NCP_FINFO(dir)->volNumber, NCP_FINFO(dir)->dirEntNum); |
744 | file, NCP_FINFO(dir)->volNumber, NCP_FINFO(dir)->dirEntNum); | ||
745 | 741 | ||
746 | err = ncp_initialize_search(server, dir, &seq); | 742 | err = ncp_initialize_search(server, dir, &seq); |
747 | if (err) { | 743 | if (err) { |
748 | DPRINTK("ncp_do_readdir: init failed, err=%d\n", err); | 744 | ncp_dbg(1, "init failed, err=%d\n", err); |
749 | return; | 745 | return; |
750 | } | 746 | } |
751 | /* We MUST NOT use server->buffer_size handshaked with server if we are | 747 | /* We MUST NOT use server->buffer_size handshaked with server if we are |
@@ -808,8 +804,7 @@ int ncp_conn_logged_in(struct super_block *sb) | |||
808 | goto out; | 804 | goto out; |
809 | result = -ENOENT; | 805 | result = -ENOENT; |
810 | if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) { | 806 | if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) { |
811 | PPRINTK("ncp_conn_logged_in: %s not found\n", | 807 | ncp_vdbg("%s not found\n", server->m.mounted_vol); |
812 | server->m.mounted_vol); | ||
813 | goto out; | 808 | goto out; |
814 | } | 809 | } |
815 | dent = sb->s_root; | 810 | dent = sb->s_root; |
@@ -822,10 +817,10 @@ int ncp_conn_logged_in(struct super_block *sb) | |||
822 | NCP_FINFO(ino)->DosDirNum = DosDirNum; | 817 | NCP_FINFO(ino)->DosDirNum = DosDirNum; |
823 | result = 0; | 818 | result = 0; |
824 | } else { | 819 | } else { |
825 | DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n"); | 820 | ncp_dbg(1, "sb->s_root->d_inode == NULL!\n"); |
826 | } | 821 | } |
827 | } else { | 822 | } else { |
828 | DPRINTK("ncpfs: sb->s_root == NULL!\n"); | 823 | ncp_dbg(1, "sb->s_root == NULL!\n"); |
829 | } | 824 | } |
830 | } else | 825 | } else |
831 | result = 0; | 826 | result = 0; |
@@ -846,7 +841,7 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsig | |||
846 | if (!ncp_conn_valid(server)) | 841 | if (!ncp_conn_valid(server)) |
847 | goto finished; | 842 | goto finished; |
848 | 843 | ||
849 | PPRINTK("ncp_lookup: server lookup for %pd2\n", dentry); | 844 | ncp_vdbg("server lookup for %pd2\n", dentry); |
850 | 845 | ||
851 | len = sizeof(__name); | 846 | len = sizeof(__name); |
852 | if (ncp_is_server_root(dir)) { | 847 | if (ncp_is_server_root(dir)) { |
@@ -854,15 +849,15 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsig | |||
854 | dentry->d_name.len, 1); | 849 | dentry->d_name.len, 1); |
855 | if (!res) | 850 | if (!res) |
856 | res = ncp_lookup_volume(server, __name, &(finfo.i)); | 851 | res = ncp_lookup_volume(server, __name, &(finfo.i)); |
857 | if (!res) | 852 | if (!res) |
858 | ncp_update_known_namespace(server, finfo.i.volNumber, NULL); | 853 | ncp_update_known_namespace(server, finfo.i.volNumber, NULL); |
859 | } else { | 854 | } else { |
860 | res = ncp_io2vol(server, __name, &len, dentry->d_name.name, | 855 | res = ncp_io2vol(server, __name, &len, dentry->d_name.name, |
861 | dentry->d_name.len, !ncp_preserve_case(dir)); | 856 | dentry->d_name.len, !ncp_preserve_case(dir)); |
862 | if (!res) | 857 | if (!res) |
863 | res = ncp_obtain_info(server, dir, __name, &(finfo.i)); | 858 | res = ncp_obtain_info(server, dir, __name, &(finfo.i)); |
864 | } | 859 | } |
865 | PPRINTK("ncp_lookup: looked for %pd2, res=%d\n", dentry, res); | 860 | ncp_vdbg("looked for %pd2, res=%d\n", dentry, res); |
866 | /* | 861 | /* |
867 | * If we didn't find an entry, make a negative dentry. | 862 | * If we didn't find an entry, make a negative dentry. |
868 | */ | 863 | */ |
@@ -886,7 +881,7 @@ add_entry: | |||
886 | } | 881 | } |
887 | 882 | ||
888 | finished: | 883 | finished: |
889 | PPRINTK("ncp_lookup: result=%d\n", error); | 884 | ncp_vdbg("result=%d\n", error); |
890 | return ERR_PTR(error); | 885 | return ERR_PTR(error); |
891 | } | 886 | } |
892 | 887 | ||
@@ -909,7 +904,7 @@ out: | |||
909 | return error; | 904 | return error; |
910 | 905 | ||
911 | out_close: | 906 | out_close: |
912 | PPRINTK("ncp_instantiate: %pd2 failed, closing file\n", dentry); | 907 | ncp_vdbg("%pd2 failed, closing file\n", dentry); |
913 | ncp_close_file(NCP_SERVER(dir), finfo->file_handle); | 908 | ncp_close_file(NCP_SERVER(dir), finfo->file_handle); |
914 | goto out; | 909 | goto out; |
915 | } | 910 | } |
@@ -923,7 +918,7 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
923 | int opmode; | 918 | int opmode; |
924 | __u8 __name[NCP_MAXPATHLEN + 1]; | 919 | __u8 __name[NCP_MAXPATHLEN + 1]; |
925 | 920 | ||
926 | PPRINTK("ncp_create_new: creating %pd2, mode=%hx\n", dentry, mode); | 921 | ncp_vdbg("creating %pd2, mode=%hx\n", dentry, mode); |
927 | 922 | ||
928 | ncp_age_dentry(server, dentry); | 923 | ncp_age_dentry(server, dentry); |
929 | len = sizeof(__name); | 924 | len = sizeof(__name); |
@@ -952,7 +947,7 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
952 | error = -ENAMETOOLONG; | 947 | error = -ENAMETOOLONG; |
953 | else if (result < 0) | 948 | else if (result < 0) |
954 | error = result; | 949 | error = result; |
955 | DPRINTK("ncp_create: %pd2 failed\n", dentry); | 950 | ncp_dbg(1, "%pd2 failed\n", dentry); |
956 | goto out; | 951 | goto out; |
957 | } | 952 | } |
958 | opmode = O_WRONLY; | 953 | opmode = O_WRONLY; |
@@ -985,7 +980,7 @@ static int ncp_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
985 | int error, len; | 980 | int error, len; |
986 | __u8 __name[NCP_MAXPATHLEN + 1]; | 981 | __u8 __name[NCP_MAXPATHLEN + 1]; |
987 | 982 | ||
988 | DPRINTK("ncp_mkdir: making %pd2\n", dentry); | 983 | ncp_dbg(1, "making %pd2\n", dentry); |
989 | 984 | ||
990 | ncp_age_dentry(server, dentry); | 985 | ncp_age_dentry(server, dentry); |
991 | len = sizeof(__name); | 986 | len = sizeof(__name); |
@@ -1022,7 +1017,7 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry) | |||
1022 | int error, result, len; | 1017 | int error, result, len; |
1023 | __u8 __name[NCP_MAXPATHLEN + 1]; | 1018 | __u8 __name[NCP_MAXPATHLEN + 1]; |
1024 | 1019 | ||
1025 | DPRINTK("ncp_rmdir: removing %pd2\n", dentry); | 1020 | ncp_dbg(1, "removing %pd2\n", dentry); |
1026 | 1021 | ||
1027 | len = sizeof(__name); | 1022 | len = sizeof(__name); |
1028 | error = ncp_io2vol(server, __name, &len, dentry->d_name.name, | 1023 | error = ncp_io2vol(server, __name, &len, dentry->d_name.name, |
@@ -1067,13 +1062,13 @@ static int ncp_unlink(struct inode *dir, struct dentry *dentry) | |||
1067 | int error; | 1062 | int error; |
1068 | 1063 | ||
1069 | server = NCP_SERVER(dir); | 1064 | server = NCP_SERVER(dir); |
1070 | DPRINTK("ncp_unlink: unlinking %pd2\n", dentry); | 1065 | ncp_dbg(1, "unlinking %pd2\n", dentry); |
1071 | 1066 | ||
1072 | /* | 1067 | /* |
1073 | * Check whether to close the file ... | 1068 | * Check whether to close the file ... |
1074 | */ | 1069 | */ |
1075 | if (inode) { | 1070 | if (inode) { |
1076 | PPRINTK("ncp_unlink: closing file\n"); | 1071 | ncp_vdbg("closing file\n"); |
1077 | ncp_make_closed(inode); | 1072 | ncp_make_closed(inode); |
1078 | } | 1073 | } |
1079 | 1074 | ||
@@ -1087,7 +1082,7 @@ static int ncp_unlink(struct inode *dir, struct dentry *dentry) | |||
1087 | #endif | 1082 | #endif |
1088 | switch (error) { | 1083 | switch (error) { |
1089 | case 0x00: | 1084 | case 0x00: |
1090 | DPRINTK("ncp: removed %pd2\n", dentry); | 1085 | ncp_dbg(1, "removed %pd2\n", dentry); |
1091 | break; | 1086 | break; |
1092 | case 0x85: | 1087 | case 0x85: |
1093 | case 0x8A: | 1088 | case 0x8A: |
@@ -1120,7 +1115,7 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1120 | int old_len, new_len; | 1115 | int old_len, new_len; |
1121 | __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1]; | 1116 | __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1]; |
1122 | 1117 | ||
1123 | DPRINTK("ncp_rename: %pd2 to %pd2\n", old_dentry, new_dentry); | 1118 | ncp_dbg(1, "%pd2 to %pd2\n", old_dentry, new_dentry); |
1124 | 1119 | ||
1125 | ncp_age_dentry(server, old_dentry); | 1120 | ncp_age_dentry(server, old_dentry); |
1126 | ncp_age_dentry(server, new_dentry); | 1121 | ncp_age_dentry(server, new_dentry); |
@@ -1150,8 +1145,8 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1150 | #endif | 1145 | #endif |
1151 | switch (error) { | 1146 | switch (error) { |
1152 | case 0x00: | 1147 | case 0x00: |
1153 | DPRINTK("ncp renamed %pd -> %pd.\n", | 1148 | ncp_dbg(1, "renamed %pd -> %pd\n", |
1154 | old_dentry, new_dentry); | 1149 | old_dentry, new_dentry); |
1155 | break; | 1150 | break; |
1156 | case 0x9E: | 1151 | case 0x9E: |
1157 | error = -ENAMETOOLONG; | 1152 | error = -ENAMETOOLONG; |
@@ -1173,7 +1168,7 @@ static int ncp_mknod(struct inode * dir, struct dentry *dentry, | |||
1173 | if (!new_valid_dev(rdev)) | 1168 | if (!new_valid_dev(rdev)) |
1174 | return -EINVAL; | 1169 | return -EINVAL; |
1175 | if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) { | 1170 | if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) { |
1176 | DPRINTK(KERN_DEBUG "ncp_mknod: mode = 0%ho\n", mode); | 1171 | ncp_dbg(1, "mode = 0%ho\n", mode); |
1177 | return ncp_create_new(dir, dentry, mode, rdev, 0); | 1172 | return ncp_create_new(dir, dentry, mode, rdev, 0); |
1178 | } | 1173 | } |
1179 | return -EPERM; /* Strange, but true */ | 1174 | return -EPERM; /* Strange, but true */ |
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c index 8f5074e1ecb9..77640a8bfb87 100644 --- a/fs/ncpfs/file.c +++ b/fs/ncpfs/file.c | |||
@@ -6,6 +6,8 @@ | |||
6 | * | 6 | * |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
10 | |||
9 | #include <asm/uaccess.h> | 11 | #include <asm/uaccess.h> |
10 | 12 | ||
11 | #include <linux/time.h> | 13 | #include <linux/time.h> |
@@ -34,11 +36,11 @@ int ncp_make_open(struct inode *inode, int right) | |||
34 | 36 | ||
35 | error = -EINVAL; | 37 | error = -EINVAL; |
36 | if (!inode) { | 38 | if (!inode) { |
37 | printk(KERN_ERR "ncp_make_open: got NULL inode\n"); | 39 | pr_err("%s: got NULL inode\n", __func__); |
38 | goto out; | 40 | goto out; |
39 | } | 41 | } |
40 | 42 | ||
41 | DPRINTK("ncp_make_open: opened=%d, volume # %u, dir entry # %u\n", | 43 | ncp_dbg(1, "opened=%d, volume # %u, dir entry # %u\n", |
42 | atomic_read(&NCP_FINFO(inode)->opened), | 44 | atomic_read(&NCP_FINFO(inode)->opened), |
43 | NCP_FINFO(inode)->volNumber, | 45 | NCP_FINFO(inode)->volNumber, |
44 | NCP_FINFO(inode)->dirEntNum); | 46 | NCP_FINFO(inode)->dirEntNum); |
@@ -71,7 +73,7 @@ int ncp_make_open(struct inode *inode, int right) | |||
71 | break; | 73 | break; |
72 | } | 74 | } |
73 | if (result) { | 75 | if (result) { |
74 | PPRINTK("ncp_make_open: failed, result=%d\n", result); | 76 | ncp_vdbg("failed, result=%d\n", result); |
75 | goto out_unlock; | 77 | goto out_unlock; |
76 | } | 78 | } |
77 | /* | 79 | /* |
@@ -83,7 +85,7 @@ int ncp_make_open(struct inode *inode, int right) | |||
83 | } | 85 | } |
84 | 86 | ||
85 | access = NCP_FINFO(inode)->access; | 87 | access = NCP_FINFO(inode)->access; |
86 | PPRINTK("ncp_make_open: file open, access=%x\n", access); | 88 | ncp_vdbg("file open, access=%x\n", access); |
87 | if (access == right || access == O_RDWR) { | 89 | if (access == right || access == O_RDWR) { |
88 | atomic_inc(&NCP_FINFO(inode)->opened); | 90 | atomic_inc(&NCP_FINFO(inode)->opened); |
89 | error = 0; | 91 | error = 0; |
@@ -107,7 +109,7 @@ ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
107 | void* freepage; | 109 | void* freepage; |
108 | size_t freelen; | 110 | size_t freelen; |
109 | 111 | ||
110 | DPRINTK("ncp_file_read: enter %pd2\n", dentry); | 112 | ncp_dbg(1, "enter %pd2\n", dentry); |
111 | 113 | ||
112 | pos = *ppos; | 114 | pos = *ppos; |
113 | 115 | ||
@@ -124,7 +126,7 @@ ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
124 | 126 | ||
125 | error = ncp_make_open(inode, O_RDONLY); | 127 | error = ncp_make_open(inode, O_RDONLY); |
126 | if (error) { | 128 | if (error) { |
127 | DPRINTK(KERN_ERR "ncp_file_read: open failed, error=%d\n", error); | 129 | ncp_dbg(1, "open failed, error=%d\n", error); |
128 | return error; | 130 | return error; |
129 | } | 131 | } |
130 | 132 | ||
@@ -165,7 +167,7 @@ ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
165 | 167 | ||
166 | file_accessed(file); | 168 | file_accessed(file); |
167 | 169 | ||
168 | DPRINTK("ncp_file_read: exit %pd2\n", dentry); | 170 | ncp_dbg(1, "exit %pd2\n", dentry); |
169 | outrel: | 171 | outrel: |
170 | ncp_inode_close(inode); | 172 | ncp_inode_close(inode); |
171 | return already_read ? already_read : error; | 173 | return already_read ? already_read : error; |
@@ -182,7 +184,7 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t * | |||
182 | int errno; | 184 | int errno; |
183 | void* bouncebuffer; | 185 | void* bouncebuffer; |
184 | 186 | ||
185 | DPRINTK("ncp_file_write: enter %pd2\n", dentry); | 187 | ncp_dbg(1, "enter %pd2\n", dentry); |
186 | if ((ssize_t) count < 0) | 188 | if ((ssize_t) count < 0) |
187 | return -EINVAL; | 189 | return -EINVAL; |
188 | pos = *ppos; | 190 | pos = *ppos; |
@@ -211,7 +213,7 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t * | |||
211 | return 0; | 213 | return 0; |
212 | errno = ncp_make_open(inode, O_WRONLY); | 214 | errno = ncp_make_open(inode, O_WRONLY); |
213 | if (errno) { | 215 | if (errno) { |
214 | DPRINTK(KERN_ERR "ncp_file_write: open failed, error=%d\n", errno); | 216 | ncp_dbg(1, "open failed, error=%d\n", errno); |
215 | return errno; | 217 | return errno; |
216 | } | 218 | } |
217 | bufsize = NCP_SERVER(inode)->buffer_size; | 219 | bufsize = NCP_SERVER(inode)->buffer_size; |
@@ -261,7 +263,7 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t * | |||
261 | i_size_write(inode, pos); | 263 | i_size_write(inode, pos); |
262 | mutex_unlock(&inode->i_mutex); | 264 | mutex_unlock(&inode->i_mutex); |
263 | } | 265 | } |
264 | DPRINTK("ncp_file_write: exit %pd2\n", dentry); | 266 | ncp_dbg(1, "exit %pd2\n", dentry); |
265 | outrel: | 267 | outrel: |
266 | ncp_inode_close(inode); | 268 | ncp_inode_close(inode); |
267 | return already_written ? already_written : errno; | 269 | return already_written ? already_written : errno; |
@@ -269,7 +271,7 @@ outrel: | |||
269 | 271 | ||
270 | static int ncp_release(struct inode *inode, struct file *file) { | 272 | static int ncp_release(struct inode *inode, struct file *file) { |
271 | if (ncp_make_closed(inode)) { | 273 | if (ncp_make_closed(inode)) { |
272 | DPRINTK("ncp_release: failed to close\n"); | 274 | ncp_dbg(1, "failed to close\n"); |
273 | } | 275 | } |
274 | return 0; | 276 | return 0; |
275 | } | 277 | } |
diff --git a/fs/ncpfs/getopt.c b/fs/ncpfs/getopt.c index 0af3349de851..03ffde1f44d6 100644 --- a/fs/ncpfs/getopt.c +++ b/fs/ncpfs/getopt.c | |||
@@ -2,6 +2,8 @@ | |||
2 | * getopt.c | 2 | * getopt.c |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
6 | |||
5 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
6 | #include <linux/string.h> | 8 | #include <linux/string.h> |
7 | 9 | ||
@@ -46,8 +48,8 @@ int ncp_getopt(const char *caller, char **options, const struct ncp_option *opts | |||
46 | if (opts->has_arg & OPT_NOPARAM) { | 48 | if (opts->has_arg & OPT_NOPARAM) { |
47 | return opts->val; | 49 | return opts->val; |
48 | } | 50 | } |
49 | printk(KERN_INFO "%s: the %s option requires an argument\n", | 51 | pr_info("%s: the %s option requires an argument\n", |
50 | caller, token); | 52 | caller, token); |
51 | return -EINVAL; | 53 | return -EINVAL; |
52 | } | 54 | } |
53 | if (opts->has_arg & OPT_INT) { | 55 | if (opts->has_arg & OPT_INT) { |
@@ -57,18 +59,18 @@ int ncp_getopt(const char *caller, char **options, const struct ncp_option *opts | |||
57 | if (!*v) { | 59 | if (!*v) { |
58 | return opts->val; | 60 | return opts->val; |
59 | } | 61 | } |
60 | printk(KERN_INFO "%s: invalid numeric value in %s=%s\n", | 62 | pr_info("%s: invalid numeric value in %s=%s\n", |
61 | caller, token, val); | 63 | caller, token, val); |
62 | return -EDOM; | 64 | return -EDOM; |
63 | } | 65 | } |
64 | if (opts->has_arg & OPT_STRING) { | 66 | if (opts->has_arg & OPT_STRING) { |
65 | return opts->val; | 67 | return opts->val; |
66 | } | 68 | } |
67 | printk(KERN_INFO "%s: unexpected argument %s to the %s option\n", | 69 | pr_info("%s: unexpected argument %s to the %s option\n", |
68 | caller, val, token); | 70 | caller, val, token); |
69 | return -EINVAL; | 71 | return -EINVAL; |
70 | } | 72 | } |
71 | } | 73 | } |
72 | printk(KERN_INFO "%s: Unrecognized mount option %s\n", caller, token); | 74 | pr_info("%s: Unrecognized mount option %s\n", caller, token); |
73 | return -EOPNOTSUPP; | 75 | return -EOPNOTSUPP; |
74 | } | 76 | } |
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 647d86d2db39..e31e589369a4 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c | |||
@@ -9,6 +9,8 @@ | |||
9 | * | 9 | * |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
13 | |||
12 | #include <linux/module.h> | 14 | #include <linux/module.h> |
13 | 15 | ||
14 | #include <asm/uaccess.h> | 16 | #include <asm/uaccess.h> |
@@ -133,7 +135,7 @@ void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo) | |||
133 | NCP_FINFO(inode)->access = nwinfo->access; | 135 | NCP_FINFO(inode)->access = nwinfo->access; |
134 | memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle, | 136 | memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle, |
135 | sizeof(nwinfo->file_handle)); | 137 | sizeof(nwinfo->file_handle)); |
136 | DPRINTK("ncp_update_inode: updated %s, volnum=%d, dirent=%u\n", | 138 | ncp_dbg(1, "updated %s, volnum=%d, dirent=%u\n", |
137 | nwinfo->i.entryName, NCP_FINFO(inode)->volNumber, | 139 | nwinfo->i.entryName, NCP_FINFO(inode)->volNumber, |
138 | NCP_FINFO(inode)->dirEntNum); | 140 | NCP_FINFO(inode)->dirEntNum); |
139 | } | 141 | } |
@@ -141,8 +143,7 @@ void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo) | |||
141 | static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi) | 143 | static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi) |
142 | { | 144 | { |
143 | /* NFS namespace mode overrides others if it's set. */ | 145 | /* NFS namespace mode overrides others if it's set. */ |
144 | DPRINTK(KERN_DEBUG "ncp_update_dates_and_mode: (%s) nfs.mode=0%o\n", | 146 | ncp_dbg(1, "(%s) nfs.mode=0%o\n", nwi->entryName, nwi->nfs.mode); |
145 | nwi->entryName, nwi->nfs.mode); | ||
146 | if (nwi->nfs.mode) { | 147 | if (nwi->nfs.mode) { |
147 | /* XXX Security? */ | 148 | /* XXX Security? */ |
148 | inode->i_mode = nwi->nfs.mode; | 149 | inode->i_mode = nwi->nfs.mode; |
@@ -230,7 +231,7 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo) | |||
230 | 231 | ||
231 | ncp_update_attrs(inode, nwinfo); | 232 | ncp_update_attrs(inode, nwinfo); |
232 | 233 | ||
233 | DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode); | 234 | ncp_dbg(2, "inode->i_mode = %u\n", inode->i_mode); |
234 | 235 | ||
235 | set_nlink(inode, 1); | 236 | set_nlink(inode, 1); |
236 | inode->i_uid = server->m.uid; | 237 | inode->i_uid = server->m.uid; |
@@ -258,7 +259,7 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info) | |||
258 | struct inode *inode; | 259 | struct inode *inode; |
259 | 260 | ||
260 | if (info == NULL) { | 261 | if (info == NULL) { |
261 | printk(KERN_ERR "ncp_iget: info is NULL\n"); | 262 | pr_err("%s: info is NULL\n", __func__); |
262 | return NULL; | 263 | return NULL; |
263 | } | 264 | } |
264 | 265 | ||
@@ -290,7 +291,7 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info) | |||
290 | } | 291 | } |
291 | insert_inode_hash(inode); | 292 | insert_inode_hash(inode); |
292 | } else | 293 | } else |
293 | printk(KERN_ERR "ncp_iget: iget failed!\n"); | 294 | pr_err("%s: iget failed!\n", __func__); |
294 | return inode; | 295 | return inode; |
295 | } | 296 | } |
296 | 297 | ||
@@ -301,12 +302,12 @@ ncp_evict_inode(struct inode *inode) | |||
301 | clear_inode(inode); | 302 | clear_inode(inode); |
302 | 303 | ||
303 | if (S_ISDIR(inode->i_mode)) { | 304 | if (S_ISDIR(inode->i_mode)) { |
304 | DDPRINTK("ncp_evict_inode: put directory %ld\n", inode->i_ino); | 305 | ncp_dbg(2, "put directory %ld\n", inode->i_ino); |
305 | } | 306 | } |
306 | 307 | ||
307 | if (ncp_make_closed(inode) != 0) { | 308 | if (ncp_make_closed(inode) != 0) { |
308 | /* We can't do anything but complain. */ | 309 | /* We can't do anything but complain. */ |
309 | printk(KERN_ERR "ncp_evict_inode: could not close\n"); | 310 | pr_err("%s: could not close\n", __func__); |
310 | } | 311 | } |
311 | } | 312 | } |
312 | 313 | ||
@@ -469,9 +470,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) | |||
469 | { | 470 | { |
470 | struct ncp_mount_data_kernel data; | 471 | struct ncp_mount_data_kernel data; |
471 | struct ncp_server *server; | 472 | struct ncp_server *server; |
472 | struct file *ncp_filp; | ||
473 | struct inode *root_inode; | 473 | struct inode *root_inode; |
474 | struct inode *sock_inode; | ||
475 | struct socket *sock; | 474 | struct socket *sock; |
476 | int error; | 475 | int error; |
477 | int default_bufsize; | 476 | int default_bufsize; |
@@ -540,18 +539,10 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) | |||
540 | if (!uid_valid(data.mounted_uid) || !uid_valid(data.uid) || | 539 | if (!uid_valid(data.mounted_uid) || !uid_valid(data.uid) || |
541 | !gid_valid(data.gid)) | 540 | !gid_valid(data.gid)) |
542 | goto out; | 541 | goto out; |
543 | error = -EBADF; | 542 | sock = sockfd_lookup(data.ncp_fd, &error); |
544 | ncp_filp = fget(data.ncp_fd); | ||
545 | if (!ncp_filp) | ||
546 | goto out; | ||
547 | error = -ENOTSOCK; | ||
548 | sock_inode = file_inode(ncp_filp); | ||
549 | if (!S_ISSOCK(sock_inode->i_mode)) | ||
550 | goto out_fput; | ||
551 | sock = SOCKET_I(sock_inode); | ||
552 | if (!sock) | 543 | if (!sock) |
553 | goto out_fput; | 544 | goto out; |
554 | 545 | ||
555 | if (sock->type == SOCK_STREAM) | 546 | if (sock->type == SOCK_STREAM) |
556 | default_bufsize = 0xF000; | 547 | default_bufsize = 0xF000; |
557 | else | 548 | else |
@@ -573,27 +564,16 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) | |||
573 | if (error) | 564 | if (error) |
574 | goto out_fput; | 565 | goto out_fput; |
575 | 566 | ||
576 | server->ncp_filp = ncp_filp; | ||
577 | server->ncp_sock = sock; | 567 | server->ncp_sock = sock; |
578 | 568 | ||
579 | if (data.info_fd != -1) { | 569 | if (data.info_fd != -1) { |
580 | struct socket *info_sock; | 570 | struct socket *info_sock = sockfd_lookup(data.info_fd, &error); |
581 | |||
582 | error = -EBADF; | ||
583 | server->info_filp = fget(data.info_fd); | ||
584 | if (!server->info_filp) | ||
585 | goto out_bdi; | ||
586 | error = -ENOTSOCK; | ||
587 | sock_inode = file_inode(server->info_filp); | ||
588 | if (!S_ISSOCK(sock_inode->i_mode)) | ||
589 | goto out_fput2; | ||
590 | info_sock = SOCKET_I(sock_inode); | ||
591 | if (!info_sock) | 571 | if (!info_sock) |
592 | goto out_fput2; | 572 | goto out_bdi; |
573 | server->info_sock = info_sock; | ||
593 | error = -EBADFD; | 574 | error = -EBADFD; |
594 | if (info_sock->type != SOCK_STREAM) | 575 | if (info_sock->type != SOCK_STREAM) |
595 | goto out_fput2; | 576 | goto out_fput2; |
596 | server->info_sock = info_sock; | ||
597 | } | 577 | } |
598 | 578 | ||
599 | /* server->lock = 0; */ | 579 | /* server->lock = 0; */ |
@@ -621,7 +601,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) | |||
621 | now because of PATH_MAX changes.. */ | 601 | now because of PATH_MAX changes.. */ |
622 | if (server->m.time_out < 1) { | 602 | if (server->m.time_out < 1) { |
623 | server->m.time_out = 10; | 603 | server->m.time_out = 10; |
624 | printk(KERN_INFO "You need to recompile your ncpfs utils..\n"); | 604 | pr_info("You need to recompile your ncpfs utils..\n"); |
625 | } | 605 | } |
626 | server->m.time_out = server->m.time_out * HZ / 100; | 606 | server->m.time_out = server->m.time_out * HZ / 100; |
627 | server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG; | 607 | server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG; |
@@ -682,7 +662,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) | |||
682 | ncp_unlock_server(server); | 662 | ncp_unlock_server(server); |
683 | if (error < 0) | 663 | if (error < 0) |
684 | goto out_rxbuf; | 664 | goto out_rxbuf; |
685 | DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb)); | 665 | ncp_dbg(1, "NCP_SBP(sb) = %p\n", NCP_SBP(sb)); |
686 | 666 | ||
687 | error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */ | 667 | error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */ |
688 | #ifdef CONFIG_NCPFS_PACKET_SIGNING | 668 | #ifdef CONFIG_NCPFS_PACKET_SIGNING |
@@ -710,7 +690,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) | |||
710 | if (ncp_negotiate_buffersize(server, default_bufsize, | 690 | if (ncp_negotiate_buffersize(server, default_bufsize, |
711 | &(server->buffer_size)) != 0) | 691 | &(server->buffer_size)) != 0) |
712 | goto out_disconnect; | 692 | goto out_disconnect; |
713 | DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size); | 693 | ncp_dbg(1, "bufsize = %d\n", server->buffer_size); |
714 | 694 | ||
715 | memset(&finfo, 0, sizeof(finfo)); | 695 | memset(&finfo, 0, sizeof(finfo)); |
716 | finfo.i.attributes = aDIR; | 696 | finfo.i.attributes = aDIR; |
@@ -739,7 +719,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) | |||
739 | root_inode = ncp_iget(sb, &finfo); | 719 | root_inode = ncp_iget(sb, &finfo); |
740 | if (!root_inode) | 720 | if (!root_inode) |
741 | goto out_disconnect; | 721 | goto out_disconnect; |
742 | DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber); | 722 | ncp_dbg(1, "root vol=%d\n", NCP_FINFO(root_inode)->volNumber); |
743 | sb->s_root = d_make_root(root_inode); | 723 | sb->s_root = d_make_root(root_inode); |
744 | if (!sb->s_root) | 724 | if (!sb->s_root) |
745 | goto out_disconnect; | 725 | goto out_disconnect; |
@@ -765,17 +745,12 @@ out_nls: | |||
765 | mutex_destroy(&server->root_setup_lock); | 745 | mutex_destroy(&server->root_setup_lock); |
766 | mutex_destroy(&server->mutex); | 746 | mutex_destroy(&server->mutex); |
767 | out_fput2: | 747 | out_fput2: |
768 | if (server->info_filp) | 748 | if (server->info_sock) |
769 | fput(server->info_filp); | 749 | sockfd_put(server->info_sock); |
770 | out_bdi: | 750 | out_bdi: |
771 | bdi_destroy(&server->bdi); | 751 | bdi_destroy(&server->bdi); |
772 | out_fput: | 752 | out_fput: |
773 | /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>: | 753 | sockfd_put(sock); |
774 | * | ||
775 | * The previously used put_filp(ncp_filp); was bogus, since | ||
776 | * it doesn't perform proper unlocking. | ||
777 | */ | ||
778 | fput(ncp_filp); | ||
779 | out: | 754 | out: |
780 | put_pid(data.wdog_pid); | 755 | put_pid(data.wdog_pid); |
781 | sb->s_fs_info = NULL; | 756 | sb->s_fs_info = NULL; |
@@ -808,9 +783,9 @@ static void ncp_put_super(struct super_block *sb) | |||
808 | mutex_destroy(&server->root_setup_lock); | 783 | mutex_destroy(&server->root_setup_lock); |
809 | mutex_destroy(&server->mutex); | 784 | mutex_destroy(&server->mutex); |
810 | 785 | ||
811 | if (server->info_filp) | 786 | if (server->info_sock) |
812 | fput(server->info_filp); | 787 | sockfd_put(server->info_sock); |
813 | fput(server->ncp_filp); | 788 | sockfd_put(server->ncp_sock); |
814 | kill_pid(server->m.wdog_pid, SIGTERM, 1); | 789 | kill_pid(server->m.wdog_pid, SIGTERM, 1); |
815 | put_pid(server->m.wdog_pid); | 790 | put_pid(server->m.wdog_pid); |
816 | 791 | ||
@@ -985,8 +960,7 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr) | |||
985 | if ((attr->ia_valid & ATTR_SIZE) != 0) { | 960 | if ((attr->ia_valid & ATTR_SIZE) != 0) { |
986 | int written; | 961 | int written; |
987 | 962 | ||
988 | DPRINTK("ncpfs: trying to change size to %ld\n", | 963 | ncp_dbg(1, "trying to change size to %llu\n", attr->ia_size); |
989 | attr->ia_size); | ||
990 | 964 | ||
991 | if ((result = ncp_make_open(inode, O_WRONLY)) < 0) { | 965 | if ((result = ncp_make_open(inode, O_WRONLY)) < 0) { |
992 | result = -EACCES; | 966 | result = -EACCES; |
@@ -1072,7 +1046,7 @@ MODULE_ALIAS_FS("ncpfs"); | |||
1072 | static int __init init_ncp_fs(void) | 1046 | static int __init init_ncp_fs(void) |
1073 | { | 1047 | { |
1074 | int err; | 1048 | int err; |
1075 | DPRINTK("ncpfs: init_ncp_fs called\n"); | 1049 | ncp_dbg(1, "called\n"); |
1076 | 1050 | ||
1077 | err = init_inodecache(); | 1051 | err = init_inodecache(); |
1078 | if (err) | 1052 | if (err) |
@@ -1089,7 +1063,7 @@ out1: | |||
1089 | 1063 | ||
1090 | static void __exit exit_ncp_fs(void) | 1064 | static void __exit exit_ncp_fs(void) |
1091 | { | 1065 | { |
1092 | DPRINTK("ncpfs: exit_ncp_fs called\n"); | 1066 | ncp_dbg(1, "called\n"); |
1093 | unregister_filesystem(&ncp_fs_type); | 1067 | unregister_filesystem(&ncp_fs_type); |
1094 | destroy_inodecache(); | 1068 | destroy_inodecache(); |
1095 | } | 1069 | } |
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c index 60426ccb3b65..d5659d96ee7f 100644 --- a/fs/ncpfs/ioctl.c +++ b/fs/ncpfs/ioctl.c | |||
@@ -41,7 +41,7 @@ ncp_get_fs_info(struct ncp_server * server, struct inode *inode, | |||
41 | return -EFAULT; | 41 | return -EFAULT; |
42 | 42 | ||
43 | if (info.version != NCP_GET_FS_INFO_VERSION) { | 43 | if (info.version != NCP_GET_FS_INFO_VERSION) { |
44 | DPRINTK("info.version invalid: %d\n", info.version); | 44 | ncp_dbg(1, "info.version invalid: %d\n", info.version); |
45 | return -EINVAL; | 45 | return -EINVAL; |
46 | } | 46 | } |
47 | /* TODO: info.addr = server->m.serv_addr; */ | 47 | /* TODO: info.addr = server->m.serv_addr; */ |
@@ -66,7 +66,7 @@ ncp_get_fs_info_v2(struct ncp_server * server, struct inode *inode, | |||
66 | return -EFAULT; | 66 | return -EFAULT; |
67 | 67 | ||
68 | if (info2.version != NCP_GET_FS_INFO_VERSION_V2) { | 68 | if (info2.version != NCP_GET_FS_INFO_VERSION_V2) { |
69 | DPRINTK("info.version invalid: %d\n", info2.version); | 69 | ncp_dbg(1, "info.version invalid: %d\n", info2.version); |
70 | return -EINVAL; | 70 | return -EINVAL; |
71 | } | 71 | } |
72 | info2.mounted_uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid); | 72 | info2.mounted_uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid); |
@@ -132,7 +132,7 @@ ncp_get_compat_fs_info_v2(struct ncp_server * server, struct inode *inode, | |||
132 | return -EFAULT; | 132 | return -EFAULT; |
133 | 133 | ||
134 | if (info2.version != NCP_GET_FS_INFO_VERSION_V2) { | 134 | if (info2.version != NCP_GET_FS_INFO_VERSION_V2) { |
135 | DPRINTK("info.version invalid: %d\n", info2.version); | 135 | ncp_dbg(1, "info.version invalid: %d\n", info2.version); |
136 | return -EINVAL; | 136 | return -EINVAL; |
137 | } | 137 | } |
138 | info2.mounted_uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid); | 138 | info2.mounted_uid = from_kuid_munged(current_user_ns(), server->m.mounted_uid); |
@@ -308,8 +308,7 @@ static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg | |||
308 | else | 308 | else |
309 | result = server->reply_size; | 309 | result = server->reply_size; |
310 | ncp_unlock_server(server); | 310 | ncp_unlock_server(server); |
311 | DPRINTK("ncp_ioctl: copy %d bytes\n", | 311 | ncp_dbg(1, "copy %d bytes\n", result); |
312 | result); | ||
313 | if (result >= 0) | 312 | if (result >= 0) |
314 | if (copy_to_user(request.data, bouncebuffer, result)) | 313 | if (copy_to_user(request.data, bouncebuffer, result)) |
315 | result = -EFAULT; | 314 | result = -EFAULT; |
@@ -385,9 +384,9 @@ static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg | |||
385 | sr.namespace = server->name_space[sr.volNumber]; | 384 | sr.namespace = server->name_space[sr.volNumber]; |
386 | result = 0; | 385 | result = 0; |
387 | } else | 386 | } else |
388 | DPRINTK("ncpfs: s_root->d_inode==NULL\n"); | 387 | ncp_dbg(1, "s_root->d_inode==NULL\n"); |
389 | } else | 388 | } else |
390 | DPRINTK("ncpfs: s_root==NULL\n"); | 389 | ncp_dbg(1, "s_root==NULL\n"); |
391 | } else { | 390 | } else { |
392 | sr.volNumber = -1; | 391 | sr.volNumber = -1; |
393 | sr.namespace = 0; | 392 | sr.namespace = 0; |
@@ -440,11 +439,11 @@ static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg | |||
440 | NCP_FINFO(s_inode)->DosDirNum = dosde; | 439 | NCP_FINFO(s_inode)->DosDirNum = dosde; |
441 | server->root_setuped = 1; | 440 | server->root_setuped = 1; |
442 | } else { | 441 | } else { |
443 | DPRINTK("ncpfs: s_root->d_inode==NULL\n"); | 442 | ncp_dbg(1, "s_root->d_inode==NULL\n"); |
444 | result = -EIO; | 443 | result = -EIO; |
445 | } | 444 | } |
446 | } else { | 445 | } else { |
447 | DPRINTK("ncpfs: s_root==NULL\n"); | 446 | ncp_dbg(1, "s_root==NULL\n"); |
448 | result = -EIO; | 447 | result = -EIO; |
449 | } | 448 | } |
450 | } | 449 | } |
diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c index 3c5dd55d284c..b359d12eb359 100644 --- a/fs/ncpfs/mmap.c +++ b/fs/ncpfs/mmap.c | |||
@@ -107,7 +107,7 @@ int ncp_mmap(struct file *file, struct vm_area_struct *vma) | |||
107 | { | 107 | { |
108 | struct inode *inode = file_inode(file); | 108 | struct inode *inode = file_inode(file); |
109 | 109 | ||
110 | DPRINTK("ncp_mmap: called\n"); | 110 | ncp_dbg(1, "called\n"); |
111 | 111 | ||
112 | if (!ncp_conn_valid(NCP_SERVER(inode))) | 112 | if (!ncp_conn_valid(NCP_SERVER(inode))) |
113 | return -EIO; | 113 | return -EIO; |
diff --git a/fs/ncpfs/ncp_fs.h b/fs/ncpfs/ncp_fs.h index 31831afe1c3b..b9f69e1b1f43 100644 --- a/fs/ncpfs/ncp_fs.h +++ b/fs/ncpfs/ncp_fs.h | |||
@@ -2,30 +2,32 @@ | |||
2 | #include "ncp_fs_i.h" | 2 | #include "ncp_fs_i.h" |
3 | #include "ncp_fs_sb.h" | 3 | #include "ncp_fs_sb.h" |
4 | 4 | ||
5 | /* define because it is easy to change PRINTK to {*}PRINTK */ | ||
6 | #define PRINTK(format, args...) printk(KERN_DEBUG format , ## args) | ||
7 | |||
8 | #undef NCPFS_PARANOIA | 5 | #undef NCPFS_PARANOIA |
9 | #ifdef NCPFS_PARANOIA | 6 | #ifdef NCPFS_PARANOIA |
10 | #define PPRINTK(format, args...) PRINTK(format , ## args) | 7 | #define ncp_vdbg(fmt, ...) \ |
8 | pr_debug(fmt, ##__VA_ARGS__) | ||
11 | #else | 9 | #else |
12 | #define PPRINTK(format, args...) | 10 | #define ncp_vdbg(fmt, ...) \ |
11 | do { \ | ||
12 | if (0) \ | ||
13 | pr_debug(fmt, ##__VA_ARGS__); \ | ||
14 | } while (0) | ||
13 | #endif | 15 | #endif |
14 | 16 | ||
15 | #ifndef DEBUG_NCP | 17 | #ifndef DEBUG_NCP |
16 | #define DEBUG_NCP 0 | 18 | #define DEBUG_NCP 0 |
17 | #endif | 19 | #endif |
18 | #if DEBUG_NCP > 0 | 20 | |
19 | #define DPRINTK(format, args...) PRINTK(format , ## args) | 21 | #if DEBUG_NCP > 0 && !defined(DEBUG) |
20 | #else | 22 | #define DEBUG |
21 | #define DPRINTK(format, args...) | ||
22 | #endif | ||
23 | #if DEBUG_NCP > 1 | ||
24 | #define DDPRINTK(format, args...) PRINTK(format , ## args) | ||
25 | #else | ||
26 | #define DDPRINTK(format, args...) | ||
27 | #endif | 23 | #endif |
28 | 24 | ||
25 | #define ncp_dbg(level, fmt, ...) \ | ||
26 | do { \ | ||
27 | if (level <= DEBUG_NCP) \ | ||
28 | pr_debug(fmt, ##__VA_ARGS__); \ | ||
29 | } while (0) | ||
30 | |||
29 | #define NCP_MAX_RPC_TIMEOUT (6*HZ) | 31 | #define NCP_MAX_RPC_TIMEOUT (6*HZ) |
30 | 32 | ||
31 | 33 | ||
diff --git a/fs/ncpfs/ncp_fs_sb.h b/fs/ncpfs/ncp_fs_sb.h index b81e97adc5a9..55e26fd80886 100644 --- a/fs/ncpfs/ncp_fs_sb.h +++ b/fs/ncpfs/ncp_fs_sb.h | |||
@@ -45,9 +45,7 @@ struct ncp_server { | |||
45 | 45 | ||
46 | __u8 name_space[NCP_NUMBER_OF_VOLUMES + 2]; | 46 | __u8 name_space[NCP_NUMBER_OF_VOLUMES + 2]; |
47 | 47 | ||
48 | struct file *ncp_filp; /* File pointer to ncp socket */ | ||
49 | struct socket *ncp_sock;/* ncp socket */ | 48 | struct socket *ncp_sock;/* ncp socket */ |
50 | struct file *info_filp; | ||
51 | struct socket *info_sock; | 49 | struct socket *info_sock; |
52 | 50 | ||
53 | u8 sequence; | 51 | u8 sequence; |
@@ -111,7 +109,7 @@ struct ncp_server { | |||
111 | 109 | ||
112 | spinlock_t requests_lock; /* Lock accesses to tx.requests, tx.creq and rcv.creq when STREAM mode */ | 110 | spinlock_t requests_lock; /* Lock accesses to tx.requests, tx.creq and rcv.creq when STREAM mode */ |
113 | 111 | ||
114 | void (*data_ready)(struct sock* sk, int len); | 112 | void (*data_ready)(struct sock* sk); |
115 | void (*error_report)(struct sock* sk); | 113 | void (*error_report)(struct sock* sk); |
116 | void (*write_space)(struct sock* sk); /* STREAM mode only */ | 114 | void (*write_space)(struct sock* sk); /* STREAM mode only */ |
117 | struct { | 115 | struct { |
@@ -153,7 +151,7 @@ extern void ncp_tcp_tx_proc(struct work_struct *work); | |||
153 | extern void ncpdgram_rcv_proc(struct work_struct *work); | 151 | extern void ncpdgram_rcv_proc(struct work_struct *work); |
154 | extern void ncpdgram_timeout_proc(struct work_struct *work); | 152 | extern void ncpdgram_timeout_proc(struct work_struct *work); |
155 | extern void ncpdgram_timeout_call(unsigned long server); | 153 | extern void ncpdgram_timeout_call(unsigned long server); |
156 | extern void ncp_tcp_data_ready(struct sock* sk, int len); | 154 | extern void ncp_tcp_data_ready(struct sock* sk); |
157 | extern void ncp_tcp_write_space(struct sock* sk); | 155 | extern void ncp_tcp_write_space(struct sock* sk); |
158 | extern void ncp_tcp_error_report(struct sock* sk); | 156 | extern void ncp_tcp_error_report(struct sock* sk); |
159 | 157 | ||
diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c index 981a95617fc9..482387532f54 100644 --- a/fs/ncpfs/ncplib_kernel.c +++ b/fs/ncpfs/ncplib_kernel.c | |||
@@ -9,14 +9,14 @@ | |||
9 | * | 9 | * |
10 | */ | 10 | */ |
11 | 11 | ||
12 | 12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
13 | 13 | ||
14 | #include "ncp_fs.h" | 14 | #include "ncp_fs.h" |
15 | 15 | ||
16 | static inline void assert_server_locked(struct ncp_server *server) | 16 | static inline void assert_server_locked(struct ncp_server *server) |
17 | { | 17 | { |
18 | if (server->lock == 0) { | 18 | if (server->lock == 0) { |
19 | DPRINTK("ncpfs: server not locked!\n"); | 19 | ncp_dbg(1, "server not locked!\n"); |
20 | } | 20 | } |
21 | } | 21 | } |
22 | 22 | ||
@@ -75,7 +75,7 @@ static void ncp_add_pstring(struct ncp_server *server, const char *s) | |||
75 | int len = strlen(s); | 75 | int len = strlen(s); |
76 | assert_server_locked(server); | 76 | assert_server_locked(server); |
77 | if (len > 255) { | 77 | if (len > 255) { |
78 | DPRINTK("ncpfs: string too long: %s\n", s); | 78 | ncp_dbg(1, "string too long: %s\n", s); |
79 | len = 255; | 79 | len = 255; |
80 | } | 80 | } |
81 | ncp_add_byte(server, len); | 81 | ncp_add_byte(server, len); |
@@ -225,7 +225,7 @@ int ncp_get_volume_info_with_number(struct ncp_server* server, | |||
225 | result = -EIO; | 225 | result = -EIO; |
226 | len = ncp_reply_byte(server, 29); | 226 | len = ncp_reply_byte(server, 29); |
227 | if (len > NCP_VOLNAME_LEN) { | 227 | if (len > NCP_VOLNAME_LEN) { |
228 | DPRINTK("ncpfs: volume name too long: %d\n", len); | 228 | ncp_dbg(1, "volume name too long: %d\n", len); |
229 | goto out; | 229 | goto out; |
230 | } | 230 | } |
231 | memcpy(&(target->volume_name), ncp_reply_data(server, 30), len); | 231 | memcpy(&(target->volume_name), ncp_reply_data(server, 30), len); |
@@ -259,7 +259,7 @@ int ncp_get_directory_info(struct ncp_server* server, __u8 n, | |||
259 | result = -EIO; | 259 | result = -EIO; |
260 | len = ncp_reply_byte(server, 21); | 260 | len = ncp_reply_byte(server, 21); |
261 | if (len > NCP_VOLNAME_LEN) { | 261 | if (len > NCP_VOLNAME_LEN) { |
262 | DPRINTK("ncpfs: volume name too long: %d\n", len); | 262 | ncp_dbg(1, "volume name too long: %d\n", len); |
263 | goto out; | 263 | goto out; |
264 | } | 264 | } |
265 | memcpy(&(target->volume_name), ncp_reply_data(server, 22), len); | 265 | memcpy(&(target->volume_name), ncp_reply_data(server, 22), len); |
@@ -295,9 +295,9 @@ ncp_make_closed(struct inode *inode) | |||
295 | err = ncp_close_file(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle); | 295 | err = ncp_close_file(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle); |
296 | 296 | ||
297 | if (!err) | 297 | if (!err) |
298 | PPRINTK("ncp_make_closed: volnum=%d, dirent=%u, error=%d\n", | 298 | ncp_vdbg("volnum=%d, dirent=%u, error=%d\n", |
299 | NCP_FINFO(inode)->volNumber, | 299 | NCP_FINFO(inode)->volNumber, |
300 | NCP_FINFO(inode)->dirEntNum, err); | 300 | NCP_FINFO(inode)->dirEntNum, err); |
301 | } | 301 | } |
302 | mutex_unlock(&NCP_FINFO(inode)->open_mutex); | 302 | mutex_unlock(&NCP_FINFO(inode)->open_mutex); |
303 | return err; | 303 | return err; |
@@ -394,8 +394,7 @@ int ncp_obtain_nfs_info(struct ncp_server *server, | |||
394 | 394 | ||
395 | if ((result = ncp_request(server, 87)) == 0) { | 395 | if ((result = ncp_request(server, 87)) == 0) { |
396 | ncp_extract_nfs_info(ncp_reply_data(server, 0), &target->nfs); | 396 | ncp_extract_nfs_info(ncp_reply_data(server, 0), &target->nfs); |
397 | DPRINTK(KERN_DEBUG | 397 | ncp_dbg(1, "(%s) mode=0%o, rdev=0x%x\n", |
398 | "ncp_obtain_nfs_info: (%s) mode=0%o, rdev=0x%x\n", | ||
399 | target->entryName, target->nfs.mode, | 398 | target->entryName, target->nfs.mode, |
400 | target->nfs.rdev); | 399 | target->nfs.rdev); |
401 | } else { | 400 | } else { |
@@ -425,7 +424,7 @@ int ncp_obtain_info(struct ncp_server *server, struct inode *dir, const char *pa | |||
425 | int result; | 424 | int result; |
426 | 425 | ||
427 | if (target == NULL) { | 426 | if (target == NULL) { |
428 | printk(KERN_ERR "ncp_obtain_info: invalid call\n"); | 427 | pr_err("%s: invalid call\n", __func__); |
429 | return -EINVAL; | 428 | return -EINVAL; |
430 | } | 429 | } |
431 | ncp_init_request(server); | 430 | ncp_init_request(server); |
@@ -498,7 +497,7 @@ ncp_get_known_namespace(struct ncp_server *server, __u8 volume) | |||
498 | namespace = ncp_reply_data(server, 2); | 497 | namespace = ncp_reply_data(server, 2); |
499 | 498 | ||
500 | while (no_namespaces > 0) { | 499 | while (no_namespaces > 0) { |
501 | DPRINTK("get_namespaces: found %d on %d\n", *namespace, volume); | 500 | ncp_dbg(1, "found %d on %d\n", *namespace, volume); |
502 | 501 | ||
503 | #ifdef CONFIG_NCPFS_NFS_NS | 502 | #ifdef CONFIG_NCPFS_NFS_NS |
504 | if ((*namespace == NW_NS_NFS) && !(server->m.flags&NCP_MOUNT_NO_NFS)) | 503 | if ((*namespace == NW_NS_NFS) && !(server->m.flags&NCP_MOUNT_NO_NFS)) |
@@ -531,8 +530,7 @@ ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns) | |||
531 | if (ret_ns) | 530 | if (ret_ns) |
532 | *ret_ns = ns; | 531 | *ret_ns = ns; |
533 | 532 | ||
534 | DPRINTK("lookup_vol: namespace[%d] = %d\n", | 533 | ncp_dbg(1, "namespace[%d] = %d\n", volume, server->name_space[volume]); |
535 | volume, server->name_space[volume]); | ||
536 | 534 | ||
537 | if (server->name_space[volume] == ns) | 535 | if (server->name_space[volume] == ns) |
538 | return 0; | 536 | return 0; |
@@ -596,7 +594,7 @@ ncp_get_volume_root(struct ncp_server *server, | |||
596 | { | 594 | { |
597 | int result; | 595 | int result; |
598 | 596 | ||
599 | DPRINTK("ncp_get_volume_root: looking up vol %s\n", volname); | 597 | ncp_dbg(1, "looking up vol %s\n", volname); |
600 | 598 | ||
601 | ncp_init_request(server); | 599 | ncp_init_request(server); |
602 | ncp_add_byte(server, 22); /* Subfunction: Generate dir handle */ | 600 | ncp_add_byte(server, 22); /* Subfunction: Generate dir handle */ |
diff --git a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c index 3a1587222c8a..471bc3d1139e 100644 --- a/fs/ncpfs/sock.c +++ b/fs/ncpfs/sock.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * | 8 | * |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
11 | 12 | ||
12 | #include <linux/time.h> | 13 | #include <linux/time.h> |
13 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
@@ -96,11 +97,11 @@ static void ncp_req_put(struct ncp_request_reply *req) | |||
96 | kfree(req); | 97 | kfree(req); |
97 | } | 98 | } |
98 | 99 | ||
99 | void ncp_tcp_data_ready(struct sock *sk, int len) | 100 | void ncp_tcp_data_ready(struct sock *sk) |
100 | { | 101 | { |
101 | struct ncp_server *server = sk->sk_user_data; | 102 | struct ncp_server *server = sk->sk_user_data; |
102 | 103 | ||
103 | server->data_ready(sk, len); | 104 | server->data_ready(sk); |
104 | schedule_work(&server->rcv.tq); | 105 | schedule_work(&server->rcv.tq); |
105 | } | 106 | } |
106 | 107 | ||
@@ -231,7 +232,7 @@ static void __ncptcp_try_send(struct ncp_server *server) | |||
231 | return; | 232 | return; |
232 | 233 | ||
233 | if (result < 0) { | 234 | if (result < 0) { |
234 | printk(KERN_ERR "ncpfs: tcp: Send failed: %d\n", result); | 235 | pr_err("tcp: Send failed: %d\n", result); |
235 | __ncp_abort_request(server, rq, result); | 236 | __ncp_abort_request(server, rq, result); |
236 | return; | 237 | return; |
237 | } | 238 | } |
@@ -332,7 +333,7 @@ static int ncp_add_request(struct ncp_server *server, struct ncp_request_reply * | |||
332 | mutex_lock(&server->rcv.creq_mutex); | 333 | mutex_lock(&server->rcv.creq_mutex); |
333 | if (!ncp_conn_valid(server)) { | 334 | if (!ncp_conn_valid(server)) { |
334 | mutex_unlock(&server->rcv.creq_mutex); | 335 | mutex_unlock(&server->rcv.creq_mutex); |
335 | printk(KERN_ERR "ncpfs: tcp: Server died\n"); | 336 | pr_err("tcp: Server died\n"); |
336 | return -EIO; | 337 | return -EIO; |
337 | } | 338 | } |
338 | ncp_req_get(req); | 339 | ncp_req_get(req); |
@@ -405,15 +406,15 @@ void ncpdgram_rcv_proc(struct work_struct *work) | |||
405 | } | 406 | } |
406 | result = _recv(sock, buf, sizeof(buf), MSG_DONTWAIT); | 407 | result = _recv(sock, buf, sizeof(buf), MSG_DONTWAIT); |
407 | if (result < 0) { | 408 | if (result < 0) { |
408 | DPRINTK("recv failed with %d\n", result); | 409 | ncp_dbg(1, "recv failed with %d\n", result); |
409 | continue; | 410 | continue; |
410 | } | 411 | } |
411 | if (result < 10) { | 412 | if (result < 10) { |
412 | DPRINTK("too short (%u) watchdog packet\n", result); | 413 | ncp_dbg(1, "too short (%u) watchdog packet\n", result); |
413 | continue; | 414 | continue; |
414 | } | 415 | } |
415 | if (buf[9] != '?') { | 416 | if (buf[9] != '?') { |
416 | DPRINTK("bad signature (%02X) in watchdog packet\n", buf[9]); | 417 | ncp_dbg(1, "bad signature (%02X) in watchdog packet\n", buf[9]); |
417 | continue; | 418 | continue; |
418 | } | 419 | } |
419 | buf[9] = 'Y'; | 420 | buf[9] = 'Y'; |
@@ -448,7 +449,7 @@ void ncpdgram_rcv_proc(struct work_struct *work) | |||
448 | result -= 8; | 449 | result -= 8; |
449 | hdrl = sock->sk->sk_family == AF_INET ? 8 : 6; | 450 | hdrl = sock->sk->sk_family == AF_INET ? 8 : 6; |
450 | if (sign_verify_reply(server, server->rxbuf + hdrl, result - hdrl, cpu_to_le32(result), server->rxbuf + result)) { | 451 | if (sign_verify_reply(server, server->rxbuf + hdrl, result - hdrl, cpu_to_le32(result), server->rxbuf + result)) { |
451 | printk(KERN_INFO "ncpfs: Signature violation\n"); | 452 | pr_info("Signature violation\n"); |
452 | result = -EIO; | 453 | result = -EIO; |
453 | } | 454 | } |
454 | } | 455 | } |
@@ -524,7 +525,7 @@ static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len) | |||
524 | return result; | 525 | return result; |
525 | } | 526 | } |
526 | if (result > len) { | 527 | if (result > len) { |
527 | printk(KERN_ERR "ncpfs: tcp: bug in recvmsg (%u > %Zu)\n", result, len); | 528 | pr_err("tcp: bug in recvmsg (%u > %Zu)\n", result, len); |
528 | return -EIO; | 529 | return -EIO; |
529 | } | 530 | } |
530 | return result; | 531 | return result; |
@@ -552,9 +553,9 @@ static int __ncptcp_rcv_proc(struct ncp_server *server) | |||
552 | __ncptcp_abort(server); | 553 | __ncptcp_abort(server); |
553 | } | 554 | } |
554 | if (result < 0) { | 555 | if (result < 0) { |
555 | printk(KERN_ERR "ncpfs: tcp: error in recvmsg: %d\n", result); | 556 | pr_err("tcp: error in recvmsg: %d\n", result); |
556 | } else { | 557 | } else { |
557 | DPRINTK(KERN_ERR "ncpfs: tcp: EOF\n"); | 558 | ncp_dbg(1, "tcp: EOF\n"); |
558 | } | 559 | } |
559 | return -EIO; | 560 | return -EIO; |
560 | } | 561 | } |
@@ -566,20 +567,20 @@ static int __ncptcp_rcv_proc(struct ncp_server *server) | |||
566 | switch (server->rcv.state) { | 567 | switch (server->rcv.state) { |
567 | case 0: | 568 | case 0: |
568 | if (server->rcv.buf.magic != htonl(NCP_TCP_RCVD_MAGIC)) { | 569 | if (server->rcv.buf.magic != htonl(NCP_TCP_RCVD_MAGIC)) { |
569 | printk(KERN_ERR "ncpfs: tcp: Unexpected reply type %08X\n", ntohl(server->rcv.buf.magic)); | 570 | pr_err("tcp: Unexpected reply type %08X\n", ntohl(server->rcv.buf.magic)); |
570 | __ncptcp_abort(server); | 571 | __ncptcp_abort(server); |
571 | return -EIO; | 572 | return -EIO; |
572 | } | 573 | } |
573 | datalen = ntohl(server->rcv.buf.len) & 0x0FFFFFFF; | 574 | datalen = ntohl(server->rcv.buf.len) & 0x0FFFFFFF; |
574 | if (datalen < 10) { | 575 | if (datalen < 10) { |
575 | printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen); | 576 | pr_err("tcp: Unexpected reply len %d\n", datalen); |
576 | __ncptcp_abort(server); | 577 | __ncptcp_abort(server); |
577 | return -EIO; | 578 | return -EIO; |
578 | } | 579 | } |
579 | #ifdef CONFIG_NCPFS_PACKET_SIGNING | 580 | #ifdef CONFIG_NCPFS_PACKET_SIGNING |
580 | if (server->sign_active) { | 581 | if (server->sign_active) { |
581 | if (datalen < 18) { | 582 | if (datalen < 18) { |
582 | printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d\n", datalen); | 583 | pr_err("tcp: Unexpected reply len %d\n", datalen); |
583 | __ncptcp_abort(server); | 584 | __ncptcp_abort(server); |
584 | return -EIO; | 585 | return -EIO; |
585 | } | 586 | } |
@@ -604,7 +605,7 @@ cont:; | |||
604 | server->rcv.len = datalen - 10; | 605 | server->rcv.len = datalen - 10; |
605 | break; | 606 | break; |
606 | } | 607 | } |
607 | DPRINTK("ncpfs: tcp: Unexpected NCP type %02X\n", type); | 608 | ncp_dbg(1, "tcp: Unexpected NCP type %02X\n", type); |
608 | skipdata2:; | 609 | skipdata2:; |
609 | server->rcv.state = 2; | 610 | server->rcv.state = 2; |
610 | skipdata:; | 611 | skipdata:; |
@@ -614,11 +615,11 @@ skipdata:; | |||
614 | } | 615 | } |
615 | req = server->rcv.creq; | 616 | req = server->rcv.creq; |
616 | if (!req) { | 617 | if (!req) { |
617 | DPRINTK(KERN_ERR "ncpfs: Reply without appropriate request\n"); | 618 | ncp_dbg(1, "Reply without appropriate request\n"); |
618 | goto skipdata2; | 619 | goto skipdata2; |
619 | } | 620 | } |
620 | if (datalen > req->datalen + 8) { | 621 | if (datalen > req->datalen + 8) { |
621 | printk(KERN_ERR "ncpfs: tcp: Unexpected reply len %d (expected at most %Zd)\n", datalen, req->datalen + 8); | 622 | pr_err("tcp: Unexpected reply len %d (expected at most %Zd)\n", datalen, req->datalen + 8); |
622 | server->rcv.state = 3; | 623 | server->rcv.state = 3; |
623 | goto skipdata; | 624 | goto skipdata; |
624 | } | 625 | } |
@@ -638,12 +639,12 @@ skipdata:; | |||
638 | req = server->rcv.creq; | 639 | req = server->rcv.creq; |
639 | if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) { | 640 | if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) { |
640 | if (((struct ncp_reply_header*)server->rxbuf)->sequence != server->sequence) { | 641 | if (((struct ncp_reply_header*)server->rxbuf)->sequence != server->sequence) { |
641 | printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n"); | 642 | pr_err("tcp: Bad sequence number\n"); |
642 | __ncp_abort_request(server, req, -EIO); | 643 | __ncp_abort_request(server, req, -EIO); |
643 | return -EIO; | 644 | return -EIO; |
644 | } | 645 | } |
645 | if ((((struct ncp_reply_header*)server->rxbuf)->conn_low | (((struct ncp_reply_header*)server->rxbuf)->conn_high << 8)) != server->connection) { | 646 | if ((((struct ncp_reply_header*)server->rxbuf)->conn_low | (((struct ncp_reply_header*)server->rxbuf)->conn_high << 8)) != server->connection) { |
646 | printk(KERN_ERR "ncpfs: tcp: Connection number mismatch\n"); | 647 | pr_err("tcp: Connection number mismatch\n"); |
647 | __ncp_abort_request(server, req, -EIO); | 648 | __ncp_abort_request(server, req, -EIO); |
648 | return -EIO; | 649 | return -EIO; |
649 | } | 650 | } |
@@ -651,7 +652,7 @@ skipdata:; | |||
651 | #ifdef CONFIG_NCPFS_PACKET_SIGNING | 652 | #ifdef CONFIG_NCPFS_PACKET_SIGNING |
652 | if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) { | 653 | if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) { |
653 | if (sign_verify_reply(server, server->rxbuf + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) { | 654 | if (sign_verify_reply(server, server->rxbuf + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) { |
654 | printk(KERN_ERR "ncpfs: tcp: Signature violation\n"); | 655 | pr_err("tcp: Signature violation\n"); |
655 | __ncp_abort_request(server, req, -EIO); | 656 | __ncp_abort_request(server, req, -EIO); |
656 | return -EIO; | 657 | return -EIO; |
657 | } | 658 | } |
@@ -742,7 +743,7 @@ static int ncp_do_request(struct ncp_server *server, int size, | |||
742 | int result; | 743 | int result; |
743 | 744 | ||
744 | if (server->lock == 0) { | 745 | if (server->lock == 0) { |
745 | printk(KERN_ERR "ncpfs: Server not locked!\n"); | 746 | pr_err("Server not locked!\n"); |
746 | return -EIO; | 747 | return -EIO; |
747 | } | 748 | } |
748 | if (!ncp_conn_valid(server)) { | 749 | if (!ncp_conn_valid(server)) { |
@@ -781,7 +782,7 @@ static int ncp_do_request(struct ncp_server *server, int size, | |||
781 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | 782 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); |
782 | } | 783 | } |
783 | 784 | ||
784 | DDPRINTK("do_ncp_rpc_call returned %d\n", result); | 785 | ncp_dbg(2, "do_ncp_rpc_call returned %d\n", result); |
785 | 786 | ||
786 | return result; | 787 | return result; |
787 | } | 788 | } |
@@ -811,7 +812,7 @@ int ncp_request2(struct ncp_server *server, int function, | |||
811 | 812 | ||
812 | result = ncp_do_request(server, server->current_size, reply, size); | 813 | result = ncp_do_request(server, server->current_size, reply, size); |
813 | if (result < 0) { | 814 | if (result < 0) { |
814 | DPRINTK("ncp_request_error: %d\n", result); | 815 | ncp_dbg(1, "ncp_request_error: %d\n", result); |
815 | goto out; | 816 | goto out; |
816 | } | 817 | } |
817 | server->completion = reply->completion_code; | 818 | server->completion = reply->completion_code; |
@@ -822,7 +823,7 @@ int ncp_request2(struct ncp_server *server, int function, | |||
822 | result = reply->completion_code; | 823 | result = reply->completion_code; |
823 | 824 | ||
824 | if (result != 0) | 825 | if (result != 0) |
825 | PPRINTK("ncp_request: completion code=%x\n", result); | 826 | ncp_vdbg("completion code=%x\n", result); |
826 | out: | 827 | out: |
827 | return result; | 828 | return result; |
828 | } | 829 | } |
@@ -865,14 +866,14 @@ void ncp_lock_server(struct ncp_server *server) | |||
865 | { | 866 | { |
866 | mutex_lock(&server->mutex); | 867 | mutex_lock(&server->mutex); |
867 | if (server->lock) | 868 | if (server->lock) |
868 | printk(KERN_WARNING "ncp_lock_server: was locked!\n"); | 869 | pr_warn("%s: was locked!\n", __func__); |
869 | server->lock = 1; | 870 | server->lock = 1; |
870 | } | 871 | } |
871 | 872 | ||
872 | void ncp_unlock_server(struct ncp_server *server) | 873 | void ncp_unlock_server(struct ncp_server *server) |
873 | { | 874 | { |
874 | if (!server->lock) { | 875 | if (!server->lock) { |
875 | printk(KERN_WARNING "ncp_unlock_server: was not locked!\n"); | 876 | pr_warn("%s: was not locked!\n", __func__); |
876 | return; | 877 | return; |
877 | } | 878 | } |
878 | server->lock = 0; | 879 | server->lock = 0; |
diff --git a/fs/ncpfs/symlink.c b/fs/ncpfs/symlink.c index 52439ddc8de0..1a63bfdb4a65 100644 --- a/fs/ncpfs/symlink.c +++ b/fs/ncpfs/symlink.c | |||
@@ -112,7 +112,7 @@ int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { | |||
112 | __le32 attr; | 112 | __le32 attr; |
113 | unsigned int hdr; | 113 | unsigned int hdr; |
114 | 114 | ||
115 | DPRINTK("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir,dentry,symname); | 115 | ncp_dbg(1, "dir=%p, dentry=%p, symname=%s\n", dir, dentry, symname); |
116 | 116 | ||
117 | if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) | 117 | if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) |
118 | kludge = 0; | 118 | kludge = 0; |
diff --git a/fs/nfsd/acl.h b/fs/nfsd/acl.h index a812fd1b92a4..b481e1f5eecc 100644 --- a/fs/nfsd/acl.h +++ b/fs/nfsd/acl.h | |||
@@ -39,9 +39,13 @@ struct nfs4_acl; | |||
39 | struct svc_fh; | 39 | struct svc_fh; |
40 | struct svc_rqst; | 40 | struct svc_rqst; |
41 | 41 | ||
42 | /* Maximum ACL we'll accept from client; chosen (somewhat arbitrarily) to | 42 | /* |
43 | * fit in a page: */ | 43 | * Maximum ACL we'll accept from a client; chosen (somewhat |
44 | #define NFS4_ACL_MAX 170 | 44 | * arbitrarily) so that kmalloc'ing the ACL shouldn't require a |
45 | * high-order allocation. This allows 204 ACEs on x86_64: | ||
46 | */ | ||
47 | #define NFS4_ACL_MAX ((PAGE_SIZE - sizeof(struct nfs4_acl)) \ | ||
48 | / sizeof(struct nfs4_ace)) | ||
45 | 49 | ||
46 | struct nfs4_acl *nfs4_acl_new(int); | 50 | struct nfs4_acl *nfs4_acl_new(int); |
47 | int nfs4_acl_get_whotype(char *, u32); | 51 | int nfs4_acl_get_whotype(char *, u32); |
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c index d190e33d0ec2..6f3f392d48af 100644 --- a/fs/nfsd/nfs4acl.c +++ b/fs/nfsd/nfs4acl.c | |||
@@ -542,7 +542,10 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags) | |||
542 | * up setting a 3-element effective posix ACL with all | 542 | * up setting a 3-element effective posix ACL with all |
543 | * permissions zero. | 543 | * permissions zero. |
544 | */ | 544 | */ |
545 | nace = 4 + state->users->n + state->groups->n; | 545 | if (!state->users->n && !state->groups->n) |
546 | nace = 3; | ||
547 | else /* Note we also include a MASK ACE in this case: */ | ||
548 | nace = 4 + state->users->n + state->groups->n; | ||
546 | pacl = posix_acl_alloc(nace, GFP_KERNEL); | 549 | pacl = posix_acl_alloc(nace, GFP_KERNEL); |
547 | if (!pacl) | 550 | if (!pacl) |
548 | return ERR_PTR(-ENOMEM); | 551 | return ERR_PTR(-ENOMEM); |
@@ -586,9 +589,11 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags) | |||
586 | add_to_mask(state, &state->groups->aces[i].perms); | 589 | add_to_mask(state, &state->groups->aces[i].perms); |
587 | } | 590 | } |
588 | 591 | ||
589 | pace++; | 592 | if (!state->users->n && !state->groups->n) { |
590 | pace->e_tag = ACL_MASK; | 593 | pace++; |
591 | low_mode_from_nfs4(state->mask.allow, &pace->e_perm, flags); | 594 | pace->e_tag = ACL_MASK; |
595 | low_mode_from_nfs4(state->mask.allow, &pace->e_perm, flags); | ||
596 | } | ||
592 | 597 | ||
593 | pace++; | 598 | pace++; |
594 | pace->e_tag = ACL_OTHER; | 599 | pace->e_tag = ACL_OTHER; |
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index 7f05cd140de3..39c8ef875f91 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
@@ -32,6 +32,7 @@ | |||
32 | */ | 32 | */ |
33 | 33 | ||
34 | #include <linux/sunrpc/clnt.h> | 34 | #include <linux/sunrpc/clnt.h> |
35 | #include <linux/sunrpc/xprt.h> | ||
35 | #include <linux/sunrpc/svc_xprt.h> | 36 | #include <linux/sunrpc/svc_xprt.h> |
36 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
37 | #include "nfsd.h" | 38 | #include "nfsd.h" |
@@ -635,6 +636,22 @@ static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc | |||
635 | } | 636 | } |
636 | } | 637 | } |
637 | 638 | ||
639 | static struct rpc_clnt *create_backchannel_client(struct rpc_create_args *args) | ||
640 | { | ||
641 | struct rpc_xprt *xprt; | ||
642 | |||
643 | if (args->protocol != XPRT_TRANSPORT_BC_TCP) | ||
644 | return rpc_create(args); | ||
645 | |||
646 | xprt = args->bc_xprt->xpt_bc_xprt; | ||
647 | if (xprt) { | ||
648 | xprt_get(xprt); | ||
649 | return rpc_create_xprt(args, xprt); | ||
650 | } | ||
651 | |||
652 | return rpc_create(args); | ||
653 | } | ||
654 | |||
638 | static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses) | 655 | static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses) |
639 | { | 656 | { |
640 | struct rpc_timeout timeparms = { | 657 | struct rpc_timeout timeparms = { |
@@ -674,7 +691,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c | |||
674 | args.authflavor = ses->se_cb_sec.flavor; | 691 | args.authflavor = ses->se_cb_sec.flavor; |
675 | } | 692 | } |
676 | /* Create RPC client */ | 693 | /* Create RPC client */ |
677 | client = rpc_create(&args); | 694 | client = create_backchannel_client(&args); |
678 | if (IS_ERR(client)) { | 695 | if (IS_ERR(client)) { |
679 | dprintk("NFSD: couldn't create callback client: %ld\n", | 696 | dprintk("NFSD: couldn't create callback client: %ld\n", |
680 | PTR_ERR(client)); | 697 | PTR_ERR(client)); |
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 82189b208af3..d543222babf3 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -1273,6 +1273,8 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, | |||
1273 | struct nfsd4_op *op; | 1273 | struct nfsd4_op *op; |
1274 | struct nfsd4_operation *opdesc; | 1274 | struct nfsd4_operation *opdesc; |
1275 | struct nfsd4_compound_state *cstate = &resp->cstate; | 1275 | struct nfsd4_compound_state *cstate = &resp->cstate; |
1276 | struct svc_fh *current_fh = &cstate->current_fh; | ||
1277 | struct svc_fh *save_fh = &cstate->save_fh; | ||
1276 | int slack_bytes; | 1278 | int slack_bytes; |
1277 | u32 plen = 0; | 1279 | u32 plen = 0; |
1278 | __be32 status; | 1280 | __be32 status; |
@@ -1288,11 +1290,11 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, | |||
1288 | resp->tag = args->tag; | 1290 | resp->tag = args->tag; |
1289 | resp->opcnt = 0; | 1291 | resp->opcnt = 0; |
1290 | resp->rqstp = rqstp; | 1292 | resp->rqstp = rqstp; |
1291 | resp->cstate.minorversion = args->minorversion; | 1293 | cstate->minorversion = args->minorversion; |
1292 | resp->cstate.replay_owner = NULL; | 1294 | cstate->replay_owner = NULL; |
1293 | resp->cstate.session = NULL; | 1295 | cstate->session = NULL; |
1294 | fh_init(&resp->cstate.current_fh, NFS4_FHSIZE); | 1296 | fh_init(current_fh, NFS4_FHSIZE); |
1295 | fh_init(&resp->cstate.save_fh, NFS4_FHSIZE); | 1297 | fh_init(save_fh, NFS4_FHSIZE); |
1296 | /* | 1298 | /* |
1297 | * Don't use the deferral mechanism for NFSv4; compounds make it | 1299 | * Don't use the deferral mechanism for NFSv4; compounds make it |
1298 | * too hard to avoid non-idempotency problems. | 1300 | * too hard to avoid non-idempotency problems. |
@@ -1345,20 +1347,28 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, | |||
1345 | 1347 | ||
1346 | opdesc = OPDESC(op); | 1348 | opdesc = OPDESC(op); |
1347 | 1349 | ||
1348 | if (!cstate->current_fh.fh_dentry) { | 1350 | if (!current_fh->fh_dentry) { |
1349 | if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) { | 1351 | if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) { |
1350 | op->status = nfserr_nofilehandle; | 1352 | op->status = nfserr_nofilehandle; |
1351 | goto encode_op; | 1353 | goto encode_op; |
1352 | } | 1354 | } |
1353 | } else if (cstate->current_fh.fh_export->ex_fslocs.migrated && | 1355 | } else if (current_fh->fh_export->ex_fslocs.migrated && |
1354 | !(opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) { | 1356 | !(opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) { |
1355 | op->status = nfserr_moved; | 1357 | op->status = nfserr_moved; |
1356 | goto encode_op; | 1358 | goto encode_op; |
1357 | } | 1359 | } |
1358 | 1360 | ||
1361 | fh_clear_wcc(current_fh); | ||
1362 | |||
1359 | /* If op is non-idempotent */ | 1363 | /* If op is non-idempotent */ |
1360 | if (opdesc->op_flags & OP_MODIFIES_SOMETHING) { | 1364 | if (opdesc->op_flags & OP_MODIFIES_SOMETHING) { |
1361 | plen = opdesc->op_rsize_bop(rqstp, op); | 1365 | plen = opdesc->op_rsize_bop(rqstp, op); |
1366 | /* | ||
1367 | * If there's still another operation, make sure | ||
1368 | * we'll have space to at least encode an error: | ||
1369 | */ | ||
1370 | if (resp->opcnt < args->opcnt) | ||
1371 | plen += COMPOUND_ERR_SLACK_SPACE; | ||
1362 | op->status = nfsd4_check_resp_size(resp, plen); | 1372 | op->status = nfsd4_check_resp_size(resp, plen); |
1363 | } | 1373 | } |
1364 | 1374 | ||
@@ -1377,12 +1387,12 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, | |||
1377 | clear_current_stateid(cstate); | 1387 | clear_current_stateid(cstate); |
1378 | 1388 | ||
1379 | if (need_wrongsec_check(rqstp)) | 1389 | if (need_wrongsec_check(rqstp)) |
1380 | op->status = check_nfsd_access(cstate->current_fh.fh_export, rqstp); | 1390 | op->status = check_nfsd_access(current_fh->fh_export, rqstp); |
1381 | } | 1391 | } |
1382 | 1392 | ||
1383 | encode_op: | 1393 | encode_op: |
1384 | /* Only from SEQUENCE */ | 1394 | /* Only from SEQUENCE */ |
1385 | if (resp->cstate.status == nfserr_replay_cache) { | 1395 | if (cstate->status == nfserr_replay_cache) { |
1386 | dprintk("%s NFS4.1 replay from cache\n", __func__); | 1396 | dprintk("%s NFS4.1 replay from cache\n", __func__); |
1387 | status = op->status; | 1397 | status = op->status; |
1388 | goto out; | 1398 | goto out; |
@@ -1411,10 +1421,10 @@ encode_op: | |||
1411 | nfsd4_increment_op_stats(op->opnum); | 1421 | nfsd4_increment_op_stats(op->opnum); |
1412 | } | 1422 | } |
1413 | 1423 | ||
1414 | resp->cstate.status = status; | 1424 | cstate->status = status; |
1415 | fh_put(&resp->cstate.current_fh); | 1425 | fh_put(current_fh); |
1416 | fh_put(&resp->cstate.save_fh); | 1426 | fh_put(save_fh); |
1417 | BUG_ON(resp->cstate.replay_owner); | 1427 | BUG_ON(cstate->replay_owner); |
1418 | out: | 1428 | out: |
1419 | /* Reset deferral mechanism for RPC deferrals */ | 1429 | /* Reset deferral mechanism for RPC deferrals */ |
1420 | rqstp->rq_usedeferral = 1; | 1430 | rqstp->rq_usedeferral = 1; |
@@ -1523,7 +1533,8 @@ static inline u32 nfsd4_setattr_rsize(struct svc_rqst *rqstp, struct nfsd4_op *o | |||
1523 | 1533 | ||
1524 | static inline u32 nfsd4_setclientid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) | 1534 | static inline u32 nfsd4_setclientid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) |
1525 | { | 1535 | { |
1526 | return (op_encode_hdr_size + 2 + 1024) * sizeof(__be32); | 1536 | return (op_encode_hdr_size + 2 + XDR_QUADLEN(NFS4_VERIFIER_SIZE)) * |
1537 | sizeof(__be32); | ||
1527 | } | 1538 | } |
1528 | 1539 | ||
1529 | static inline u32 nfsd4_write_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) | 1540 | static inline u32 nfsd4_write_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index d5d070fbeb35..3ba65979a3cd 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -1538,7 +1538,7 @@ out_err: | |||
1538 | } | 1538 | } |
1539 | 1539 | ||
1540 | /* | 1540 | /* |
1541 | * Cache a reply. nfsd4_check_drc_limit() has bounded the cache size. | 1541 | * Cache a reply. nfsd4_check_resp_size() has bounded the cache size. |
1542 | */ | 1542 | */ |
1543 | void | 1543 | void |
1544 | nfsd4_store_cache_entry(struct nfsd4_compoundres *resp) | 1544 | nfsd4_store_cache_entry(struct nfsd4_compoundres *resp) |
@@ -1596,7 +1596,7 @@ nfsd4_enc_sequence_replay(struct nfsd4_compoundargs *args, | |||
1596 | * The sequence operation is not cached because we can use the slot and | 1596 | * The sequence operation is not cached because we can use the slot and |
1597 | * session values. | 1597 | * session values. |
1598 | */ | 1598 | */ |
1599 | __be32 | 1599 | static __be32 |
1600 | nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp, | 1600 | nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp, |
1601 | struct nfsd4_sequence *seq) | 1601 | struct nfsd4_sequence *seq) |
1602 | { | 1602 | { |
@@ -1605,9 +1605,8 @@ nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp, | |||
1605 | 1605 | ||
1606 | dprintk("--> %s slot %p\n", __func__, slot); | 1606 | dprintk("--> %s slot %p\n", __func__, slot); |
1607 | 1607 | ||
1608 | /* Either returns 0 or nfserr_retry_uncached */ | ||
1609 | status = nfsd4_enc_sequence_replay(resp->rqstp->rq_argp, resp); | 1608 | status = nfsd4_enc_sequence_replay(resp->rqstp->rq_argp, resp); |
1610 | if (status == nfserr_retry_uncached_rep) | 1609 | if (status) |
1611 | return status; | 1610 | return status; |
1612 | 1611 | ||
1613 | /* The sequence operation has been encoded, cstate->datap set. */ | 1612 | /* The sequence operation has been encoded, cstate->datap set. */ |
@@ -2287,7 +2286,8 @@ out: | |||
2287 | if (!list_empty(&clp->cl_revoked)) | 2286 | if (!list_empty(&clp->cl_revoked)) |
2288 | seq->status_flags |= SEQ4_STATUS_RECALLABLE_STATE_REVOKED; | 2287 | seq->status_flags |= SEQ4_STATUS_RECALLABLE_STATE_REVOKED; |
2289 | out_no_session: | 2288 | out_no_session: |
2290 | kfree(conn); | 2289 | if (conn) |
2290 | free_conn(conn); | ||
2291 | spin_unlock(&nn->client_lock); | 2291 | spin_unlock(&nn->client_lock); |
2292 | return status; | 2292 | return status; |
2293 | out_put_session: | 2293 | out_put_session: |
@@ -3627,8 +3627,11 @@ static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, | |||
3627 | return nfserr_bad_stateid; | 3627 | return nfserr_bad_stateid; |
3628 | status = lookup_clientid(&stateid->si_opaque.so_clid, sessions, | 3628 | status = lookup_clientid(&stateid->si_opaque.so_clid, sessions, |
3629 | nn, &cl); | 3629 | nn, &cl); |
3630 | if (status == nfserr_stale_clientid) | 3630 | if (status == nfserr_stale_clientid) { |
3631 | if (sessions) | ||
3632 | return nfserr_bad_stateid; | ||
3631 | return nfserr_stale_stateid; | 3633 | return nfserr_stale_stateid; |
3634 | } | ||
3632 | if (status) | 3635 | if (status) |
3633 | return status; | 3636 | return status; |
3634 | *s = find_stateid_by_type(cl, stateid, typemask); | 3637 | *s = find_stateid_by_type(cl, stateid, typemask); |
@@ -5062,7 +5065,6 @@ nfs4_state_destroy_net(struct net *net) | |||
5062 | int i; | 5065 | int i; |
5063 | struct nfs4_client *clp = NULL; | 5066 | struct nfs4_client *clp = NULL; |
5064 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); | 5067 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); |
5065 | struct rb_node *node, *tmp; | ||
5066 | 5068 | ||
5067 | for (i = 0; i < CLIENT_HASH_SIZE; i++) { | 5069 | for (i = 0; i < CLIENT_HASH_SIZE; i++) { |
5068 | while (!list_empty(&nn->conf_id_hashtbl[i])) { | 5070 | while (!list_empty(&nn->conf_id_hashtbl[i])) { |
@@ -5071,13 +5073,11 @@ nfs4_state_destroy_net(struct net *net) | |||
5071 | } | 5073 | } |
5072 | } | 5074 | } |
5073 | 5075 | ||
5074 | node = rb_first(&nn->unconf_name_tree); | 5076 | for (i = 0; i < CLIENT_HASH_SIZE; i++) { |
5075 | while (node != NULL) { | 5077 | while (!list_empty(&nn->unconf_id_hashtbl[i])) { |
5076 | tmp = node; | 5078 | clp = list_entry(nn->unconf_id_hashtbl[i].next, struct nfs4_client, cl_idhash); |
5077 | node = rb_next(tmp); | 5079 | destroy_client(clp); |
5078 | clp = rb_entry(tmp, struct nfs4_client, cl_namenode); | 5080 | } |
5079 | rb_erase(tmp, &nn->unconf_name_tree); | ||
5080 | destroy_client(clp); | ||
5081 | } | 5081 | } |
5082 | 5082 | ||
5083 | kfree(nn->sessionid_hashtbl); | 5083 | kfree(nn->sessionid_hashtbl); |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 63f2395c57ed..2723c1badd01 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -294,7 +294,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, | |||
294 | READ32(nace); | 294 | READ32(nace); |
295 | 295 | ||
296 | if (nace > NFS4_ACL_MAX) | 296 | if (nace > NFS4_ACL_MAX) |
297 | return nfserr_resource; | 297 | return nfserr_fbig; |
298 | 298 | ||
299 | *acl = nfs4_acl_new(nace); | 299 | *acl = nfs4_acl_new(nace); |
300 | if (*acl == NULL) | 300 | if (*acl == NULL) |
@@ -1222,7 +1222,6 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write) | |||
1222 | } | 1222 | } |
1223 | write->wr_head.iov_base = p; | 1223 | write->wr_head.iov_base = p; |
1224 | write->wr_head.iov_len = avail; | 1224 | write->wr_head.iov_len = avail; |
1225 | WARN_ON(avail != (XDR_QUADLEN(avail) << 2)); | ||
1226 | write->wr_pagelist = argp->pagelist; | 1225 | write->wr_pagelist = argp->pagelist; |
1227 | 1226 | ||
1228 | len = XDR_QUADLEN(write->wr_buflen) << 2; | 1227 | len = XDR_QUADLEN(write->wr_buflen) << 2; |
@@ -2483,6 +2482,8 @@ out_acl: | |||
2483 | goto out; | 2482 | goto out; |
2484 | } | 2483 | } |
2485 | if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) { | 2484 | if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) { |
2485 | if ((buflen -= 16) < 0) | ||
2486 | goto out_resource; | ||
2486 | WRITE32(3); | 2487 | WRITE32(3); |
2487 | WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0); | 2488 | WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0); |
2488 | WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD1); | 2489 | WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD1); |
@@ -2499,8 +2500,10 @@ out: | |||
2499 | security_release_secctx(context, contextlen); | 2500 | security_release_secctx(context, contextlen); |
2500 | #endif /* CONFIG_NFSD_V4_SECURITY_LABEL */ | 2501 | #endif /* CONFIG_NFSD_V4_SECURITY_LABEL */ |
2501 | kfree(acl); | 2502 | kfree(acl); |
2502 | if (tempfh) | 2503 | if (tempfh) { |
2503 | fh_put(tempfh); | 2504 | fh_put(tempfh); |
2505 | kfree(tempfh); | ||
2506 | } | ||
2504 | return status; | 2507 | return status; |
2505 | out_nfserr: | 2508 | out_nfserr: |
2506 | status = nfserrno(err); | 2509 | status = nfserrno(err); |
@@ -3471,6 +3474,9 @@ nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, __be32 nfserr, | |||
3471 | struct nfsd4_test_stateid_id *stateid, *next; | 3474 | struct nfsd4_test_stateid_id *stateid, *next; |
3472 | __be32 *p; | 3475 | __be32 *p; |
3473 | 3476 | ||
3477 | if (nfserr) | ||
3478 | return nfserr; | ||
3479 | |||
3474 | RESERVE_SPACE(4 + (4 * test_stateid->ts_num_ids)); | 3480 | RESERVE_SPACE(4 + (4 * test_stateid->ts_num_ids)); |
3475 | *p++ = htonl(test_stateid->ts_num_ids); | 3481 | *p++ = htonl(test_stateid->ts_num_ids); |
3476 | 3482 | ||
@@ -3579,8 +3585,6 @@ __be32 nfsd4_check_resp_size(struct nfsd4_compoundres *resp, u32 pad) | |||
3579 | return 0; | 3585 | return 0; |
3580 | 3586 | ||
3581 | session = resp->cstate.session; | 3587 | session = resp->cstate.session; |
3582 | if (session == NULL) | ||
3583 | return 0; | ||
3584 | 3588 | ||
3585 | if (xb->page_len == 0) { | 3589 | if (xb->page_len == 0) { |
3586 | length = (char *)resp->p - (char *)xb->head[0].iov_base + pad; | 3590 | length = (char *)resp->p - (char *)xb->head[0].iov_base + pad; |
@@ -3620,9 +3624,17 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) | |||
3620 | BUG_ON(op->opnum < 0 || op->opnum >= ARRAY_SIZE(nfsd4_enc_ops) || | 3624 | BUG_ON(op->opnum < 0 || op->opnum >= ARRAY_SIZE(nfsd4_enc_ops) || |
3621 | !nfsd4_enc_ops[op->opnum]); | 3625 | !nfsd4_enc_ops[op->opnum]); |
3622 | op->status = nfsd4_enc_ops[op->opnum](resp, op->status, &op->u); | 3626 | op->status = nfsd4_enc_ops[op->opnum](resp, op->status, &op->u); |
3623 | /* nfsd4_check_drc_limit guarantees enough room for error status */ | 3627 | /* nfsd4_check_resp_size guarantees enough room for error status */ |
3624 | if (!op->status) | 3628 | if (!op->status) |
3625 | op->status = nfsd4_check_resp_size(resp, 0); | 3629 | op->status = nfsd4_check_resp_size(resp, 0); |
3630 | if (op->status == nfserr_resource && nfsd4_has_session(&resp->cstate)) { | ||
3631 | struct nfsd4_slot *slot = resp->cstate.slot; | ||
3632 | |||
3633 | if (slot->sl_flags & NFSD4_SLOT_CACHETHIS) | ||
3634 | op->status = nfserr_rep_too_big_to_cache; | ||
3635 | else | ||
3636 | op->status = nfserr_rep_too_big; | ||
3637 | } | ||
3626 | if (so) { | 3638 | if (so) { |
3627 | so->so_replay.rp_status = op->status; | 3639 | so->so_replay.rp_status = op->status; |
3628 | so->so_replay.rp_buflen = (char *)resp->p - (char *)(statp+1); | 3640 | so->so_replay.rp_buflen = (char *)resp->p - (char *)(statp+1); |
@@ -3691,6 +3703,12 @@ int nfsd4_release_compoundargs(void *rq, __be32 *p, void *resp) | |||
3691 | int | 3703 | int |
3692 | nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args) | 3704 | nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args) |
3693 | { | 3705 | { |
3706 | if (rqstp->rq_arg.head[0].iov_len % 4) { | ||
3707 | /* client is nuts */ | ||
3708 | dprintk("%s: compound not properly padded! (peeraddr=%pISc xid=0x%x)", | ||
3709 | __func__, svc_addr(rqstp), be32_to_cpu(rqstp->rq_xid)); | ||
3710 | return 0; | ||
3711 | } | ||
3694 | args->p = p; | 3712 | args->p = p; |
3695 | args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len; | 3713 | args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len; |
3696 | args->pagelist = rqstp->rq_arg.pages; | 3714 | args->pagelist = rqstp->rq_arg.pages; |
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 7f555179bf81..f34d9de802ab 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
@@ -699,6 +699,11 @@ static ssize_t __write_ports_addfd(char *buf, struct net *net) | |||
699 | if (err != 0 || fd < 0) | 699 | if (err != 0 || fd < 0) |
700 | return -EINVAL; | 700 | return -EINVAL; |
701 | 701 | ||
702 | if (svc_alien_sock(net, fd)) { | ||
703 | printk(KERN_ERR "%s: socket net is different to NFSd's one\n", __func__); | ||
704 | return -EINVAL; | ||
705 | } | ||
706 | |||
702 | err = nfsd_create_serv(net); | 707 | err = nfsd_create_serv(net); |
703 | if (err != 0) | 708 | if (err != 0) |
704 | return err; | 709 | return err; |
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 30f34ab02137..479eb681c27c 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h | |||
@@ -282,7 +282,7 @@ void nfsd_lockd_shutdown(void); | |||
282 | * reason. | 282 | * reason. |
283 | */ | 283 | */ |
284 | #define COMPOUND_SLACK_SPACE 140 /* OP_GETFH */ | 284 | #define COMPOUND_SLACK_SPACE 140 /* OP_GETFH */ |
285 | #define COMPOUND_ERR_SLACK_SPACE 12 /* OP_SETATTR */ | 285 | #define COMPOUND_ERR_SLACK_SPACE 16 /* OP_SETATTR */ |
286 | 286 | ||
287 | #define NFSD_LAUNDROMAT_MINTIMEOUT 1 /* seconds */ | 287 | #define NFSD_LAUNDROMAT_MINTIMEOUT 1 /* seconds */ |
288 | 288 | ||
diff --git a/fs/nfsd/nfsfh.h b/fs/nfsd/nfsfh.h index 4775bc4896c8..ad67964d0bb1 100644 --- a/fs/nfsd/nfsfh.h +++ b/fs/nfsd/nfsfh.h | |||
@@ -133,6 +133,17 @@ fh_init(struct svc_fh *fhp, int maxsize) | |||
133 | 133 | ||
134 | #ifdef CONFIG_NFSD_V3 | 134 | #ifdef CONFIG_NFSD_V3 |
135 | /* | 135 | /* |
136 | * The wcc data stored in current_fh should be cleared | ||
137 | * between compound ops. | ||
138 | */ | ||
139 | static inline void | ||
140 | fh_clear_wcc(struct svc_fh *fhp) | ||
141 | { | ||
142 | fhp->fh_post_saved = 0; | ||
143 | fhp->fh_pre_saved = 0; | ||
144 | } | ||
145 | |||
146 | /* | ||
136 | * Fill in the pre_op attr for the wcc data | 147 | * Fill in the pre_op attr for the wcc data |
137 | */ | 148 | */ |
138 | static inline void | 149 | static inline void |
@@ -152,7 +163,8 @@ fill_pre_wcc(struct svc_fh *fhp) | |||
152 | 163 | ||
153 | extern void fill_post_wcc(struct svc_fh *); | 164 | extern void fill_post_wcc(struct svc_fh *); |
154 | #else | 165 | #else |
155 | #define fill_pre_wcc(ignored) | 166 | #define fh_clear_wcc(ignored) |
167 | #define fill_pre_wcc(ignored) | ||
156 | #define fill_post_wcc(notused) | 168 | #define fill_post_wcc(notused) |
157 | #endif /* CONFIG_NFSD_V3 */ | 169 | #endif /* CONFIG_NFSD_V3 */ |
158 | 170 | ||
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index b17d93214d01..9c769a47ac5a 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c | |||
@@ -152,7 +152,7 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, | |||
152 | type = (stat->mode & S_IFMT); | 152 | type = (stat->mode & S_IFMT); |
153 | 153 | ||
154 | *p++ = htonl(nfs_ftypes[type >> 12]); | 154 | *p++ = htonl(nfs_ftypes[type >> 12]); |
155 | *p++ = htonl((u32) (stat->mode & S_IALLUGO)); | 155 | *p++ = htonl((u32) stat->mode); |
156 | *p++ = htonl((u32) stat->nlink); | 156 | *p++ = htonl((u32) stat->nlink); |
157 | *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid)); | 157 | *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid)); |
158 | *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid)); | 158 | *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid)); |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 915808b36df7..16f0673a423c 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -404,6 +404,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, | |||
404 | umode_t ftype = 0; | 404 | umode_t ftype = 0; |
405 | __be32 err; | 405 | __be32 err; |
406 | int host_err; | 406 | int host_err; |
407 | bool get_write_count; | ||
407 | int size_change = 0; | 408 | int size_change = 0; |
408 | 409 | ||
409 | if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE)) | 410 | if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE)) |
@@ -411,10 +412,18 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, | |||
411 | if (iap->ia_valid & ATTR_SIZE) | 412 | if (iap->ia_valid & ATTR_SIZE) |
412 | ftype = S_IFREG; | 413 | ftype = S_IFREG; |
413 | 414 | ||
415 | /* Callers that do fh_verify should do the fh_want_write: */ | ||
416 | get_write_count = !fhp->fh_dentry; | ||
417 | |||
414 | /* Get inode */ | 418 | /* Get inode */ |
415 | err = fh_verify(rqstp, fhp, ftype, accmode); | 419 | err = fh_verify(rqstp, fhp, ftype, accmode); |
416 | if (err) | 420 | if (err) |
417 | goto out; | 421 | goto out; |
422 | if (get_write_count) { | ||
423 | host_err = fh_want_write(fhp); | ||
424 | if (host_err) | ||
425 | return nfserrno(host_err); | ||
426 | } | ||
418 | 427 | ||
419 | dentry = fhp->fh_dentry; | 428 | dentry = fhp->fh_dentry; |
420 | inode = dentry->d_inode; | 429 | inode = dentry->d_inode; |
@@ -1706,10 +1715,10 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
1706 | dput(odentry); | 1715 | dput(odentry); |
1707 | out_nfserr: | 1716 | out_nfserr: |
1708 | err = nfserrno(host_err); | 1717 | err = nfserrno(host_err); |
1709 | 1718 | /* | |
1710 | /* we cannot reply on fh_unlock on the two filehandles, | 1719 | * We cannot rely on fh_unlock on the two filehandles, |
1711 | * as that would do the wrong thing if the two directories | 1720 | * as that would do the wrong thing if the two directories |
1712 | * were the same, so again we do it by hand | 1721 | * were the same, so again we do it by hand. |
1713 | */ | 1722 | */ |
1714 | fill_post_wcc(ffhp); | 1723 | fill_post_wcc(ffhp); |
1715 | fill_post_wcc(tfhp); | 1724 | fill_post_wcc(tfhp); |
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index d278a0d03496..5ea7df305083 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h | |||
@@ -574,8 +574,6 @@ extern __be32 nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
574 | struct nfsd4_compound_state *, | 574 | struct nfsd4_compound_state *, |
575 | struct nfsd4_setclientid_confirm *setclientid_confirm); | 575 | struct nfsd4_setclientid_confirm *setclientid_confirm); |
576 | extern void nfsd4_store_cache_entry(struct nfsd4_compoundres *resp); | 576 | extern void nfsd4_store_cache_entry(struct nfsd4_compoundres *resp); |
577 | extern __be32 nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp, | ||
578 | struct nfsd4_sequence *seq); | ||
579 | extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp, | 577 | extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp, |
580 | struct nfsd4_compound_state *, struct nfsd4_exchange_id *); | 578 | struct nfsd4_compound_state *, struct nfsd4_exchange_id *); |
581 | extern __be32 nfsd4_backchannel_ctl(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_backchannel_ctl *); | 579 | extern __be32 nfsd4_backchannel_ctl(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_backchannel_ctl *); |
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 9d8153ebacfb..f47af5e6e230 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c | |||
@@ -1704,8 +1704,6 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi) | |||
1704 | iput(bvi); | 1704 | iput(bvi); |
1705 | skip_large_index_stuff: | 1705 | skip_large_index_stuff: |
1706 | /* Setup the operations for this index inode. */ | 1706 | /* Setup the operations for this index inode. */ |
1707 | vi->i_op = NULL; | ||
1708 | vi->i_fop = NULL; | ||
1709 | vi->i_mapping->a_ops = &ntfs_mst_aops; | 1707 | vi->i_mapping->a_ops = &ntfs_mst_aops; |
1710 | vi->i_blocks = ni->allocated_size >> 9; | 1708 | vi->i_blocks = ni->allocated_size >> 9; |
1711 | /* | 1709 | /* |
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index eb649d23a4de..c6b90e670389 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c | |||
@@ -137,7 +137,7 @@ static int o2net_sys_err_translations[O2NET_ERR_MAX] = | |||
137 | static void o2net_sc_connect_completed(struct work_struct *work); | 137 | static void o2net_sc_connect_completed(struct work_struct *work); |
138 | static void o2net_rx_until_empty(struct work_struct *work); | 138 | static void o2net_rx_until_empty(struct work_struct *work); |
139 | static void o2net_shutdown_sc(struct work_struct *work); | 139 | static void o2net_shutdown_sc(struct work_struct *work); |
140 | static void o2net_listen_data_ready(struct sock *sk, int bytes); | 140 | static void o2net_listen_data_ready(struct sock *sk); |
141 | static void o2net_sc_send_keep_req(struct work_struct *work); | 141 | static void o2net_sc_send_keep_req(struct work_struct *work); |
142 | static void o2net_idle_timer(unsigned long data); | 142 | static void o2net_idle_timer(unsigned long data); |
143 | static void o2net_sc_postpone_idle(struct o2net_sock_container *sc); | 143 | static void o2net_sc_postpone_idle(struct o2net_sock_container *sc); |
@@ -597,9 +597,9 @@ static void o2net_set_nn_state(struct o2net_node *nn, | |||
597 | } | 597 | } |
598 | 598 | ||
599 | /* see o2net_register_callbacks() */ | 599 | /* see o2net_register_callbacks() */ |
600 | static void o2net_data_ready(struct sock *sk, int bytes) | 600 | static void o2net_data_ready(struct sock *sk) |
601 | { | 601 | { |
602 | void (*ready)(struct sock *sk, int bytes); | 602 | void (*ready)(struct sock *sk); |
603 | 603 | ||
604 | read_lock(&sk->sk_callback_lock); | 604 | read_lock(&sk->sk_callback_lock); |
605 | if (sk->sk_user_data) { | 605 | if (sk->sk_user_data) { |
@@ -613,7 +613,7 @@ static void o2net_data_ready(struct sock *sk, int bytes) | |||
613 | } | 613 | } |
614 | read_unlock(&sk->sk_callback_lock); | 614 | read_unlock(&sk->sk_callback_lock); |
615 | 615 | ||
616 | ready(sk, bytes); | 616 | ready(sk); |
617 | } | 617 | } |
618 | 618 | ||
619 | /* see o2net_register_callbacks() */ | 619 | /* see o2net_register_callbacks() */ |
@@ -916,57 +916,30 @@ static struct o2net_msg_handler *o2net_handler_get(u32 msg_type, u32 key) | |||
916 | 916 | ||
917 | static int o2net_recv_tcp_msg(struct socket *sock, void *data, size_t len) | 917 | static int o2net_recv_tcp_msg(struct socket *sock, void *data, size_t len) |
918 | { | 918 | { |
919 | int ret; | 919 | struct kvec vec = { .iov_len = len, .iov_base = data, }; |
920 | mm_segment_t oldfs; | 920 | struct msghdr msg = { .msg_flags = MSG_DONTWAIT, }; |
921 | struct kvec vec = { | 921 | return kernel_recvmsg(sock, &msg, &vec, 1, len, msg.msg_flags); |
922 | .iov_len = len, | ||
923 | .iov_base = data, | ||
924 | }; | ||
925 | struct msghdr msg = { | ||
926 | .msg_iovlen = 1, | ||
927 | .msg_iov = (struct iovec *)&vec, | ||
928 | .msg_flags = MSG_DONTWAIT, | ||
929 | }; | ||
930 | |||
931 | oldfs = get_fs(); | ||
932 | set_fs(get_ds()); | ||
933 | ret = sock_recvmsg(sock, &msg, len, msg.msg_flags); | ||
934 | set_fs(oldfs); | ||
935 | |||
936 | return ret; | ||
937 | } | 922 | } |
938 | 923 | ||
939 | static int o2net_send_tcp_msg(struct socket *sock, struct kvec *vec, | 924 | static int o2net_send_tcp_msg(struct socket *sock, struct kvec *vec, |
940 | size_t veclen, size_t total) | 925 | size_t veclen, size_t total) |
941 | { | 926 | { |
942 | int ret; | 927 | int ret; |
943 | mm_segment_t oldfs; | 928 | struct msghdr msg; |
944 | struct msghdr msg = { | ||
945 | .msg_iov = (struct iovec *)vec, | ||
946 | .msg_iovlen = veclen, | ||
947 | }; | ||
948 | 929 | ||
949 | if (sock == NULL) { | 930 | if (sock == NULL) { |
950 | ret = -EINVAL; | 931 | ret = -EINVAL; |
951 | goto out; | 932 | goto out; |
952 | } | 933 | } |
953 | 934 | ||
954 | oldfs = get_fs(); | 935 | ret = kernel_sendmsg(sock, &msg, vec, veclen, total); |
955 | set_fs(get_ds()); | 936 | if (likely(ret == total)) |
956 | ret = sock_sendmsg(sock, &msg, total); | 937 | return 0; |
957 | set_fs(oldfs); | 938 | mlog(ML_ERROR, "sendmsg returned %d instead of %zu\n", ret, total); |
958 | if (ret != total) { | 939 | if (ret >= 0) |
959 | mlog(ML_ERROR, "sendmsg returned %d instead of %zu\n", ret, | 940 | ret = -EPIPE; /* should be smarter, I bet */ |
960 | total); | ||
961 | if (ret >= 0) | ||
962 | ret = -EPIPE; /* should be smarter, I bet */ | ||
963 | goto out; | ||
964 | } | ||
965 | |||
966 | ret = 0; | ||
967 | out: | 941 | out: |
968 | if (ret < 0) | 942 | mlog(0, "returning error: %d\n", ret); |
969 | mlog(0, "returning error: %d\n", ret); | ||
970 | return ret; | 943 | return ret; |
971 | } | 944 | } |
972 | 945 | ||
@@ -1953,9 +1926,9 @@ static void o2net_accept_many(struct work_struct *work) | |||
1953 | cond_resched(); | 1926 | cond_resched(); |
1954 | } | 1927 | } |
1955 | 1928 | ||
1956 | static void o2net_listen_data_ready(struct sock *sk, int bytes) | 1929 | static void o2net_listen_data_ready(struct sock *sk) |
1957 | { | 1930 | { |
1958 | void (*ready)(struct sock *sk, int bytes); | 1931 | void (*ready)(struct sock *sk); |
1959 | 1932 | ||
1960 | read_lock(&sk->sk_callback_lock); | 1933 | read_lock(&sk->sk_callback_lock); |
1961 | ready = sk->sk_user_data; | 1934 | ready = sk->sk_user_data; |
@@ -1978,7 +1951,6 @@ static void o2net_listen_data_ready(struct sock *sk, int bytes) | |||
1978 | */ | 1951 | */ |
1979 | 1952 | ||
1980 | if (sk->sk_state == TCP_LISTEN) { | 1953 | if (sk->sk_state == TCP_LISTEN) { |
1981 | mlog(ML_TCP, "bytes: %d\n", bytes); | ||
1982 | queue_work(o2net_wq, &o2net_listen_work); | 1954 | queue_work(o2net_wq, &o2net_listen_work); |
1983 | } else { | 1955 | } else { |
1984 | ready = NULL; | 1956 | ready = NULL; |
@@ -1987,7 +1959,7 @@ static void o2net_listen_data_ready(struct sock *sk, int bytes) | |||
1987 | out: | 1959 | out: |
1988 | read_unlock(&sk->sk_callback_lock); | 1960 | read_unlock(&sk->sk_callback_lock); |
1989 | if (ready != NULL) | 1961 | if (ready != NULL) |
1990 | ready(sk, bytes); | 1962 | ready(sk); |
1991 | } | 1963 | } |
1992 | 1964 | ||
1993 | static int o2net_open_listening_sock(__be32 addr, __be16 port) | 1965 | static int o2net_open_listening_sock(__be32 addr, __be16 port) |
diff --git a/fs/ocfs2/cluster/tcp_internal.h b/fs/ocfs2/cluster/tcp_internal.h index 4cbcb65784a3..dc024367110a 100644 --- a/fs/ocfs2/cluster/tcp_internal.h +++ b/fs/ocfs2/cluster/tcp_internal.h | |||
@@ -165,7 +165,7 @@ struct o2net_sock_container { | |||
165 | 165 | ||
166 | /* original handlers for the sockets */ | 166 | /* original handlers for the sockets */ |
167 | void (*sc_state_change)(struct sock *sk); | 167 | void (*sc_state_change)(struct sock *sk); |
168 | void (*sc_data_ready)(struct sock *sk, int bytes); | 168 | void (*sc_data_ready)(struct sock *sk); |
169 | 169 | ||
170 | u32 sc_msg_key; | 170 | u32 sc_msg_key; |
171 | u16 sc_msg_type; | 171 | u16 sc_msg_type; |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index ff33c5ef87f2..8970dcf74de5 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -2367,15 +2367,18 @@ relock: | |||
2367 | 2367 | ||
2368 | if (direct_io) { | 2368 | if (direct_io) { |
2369 | written = generic_file_direct_write(iocb, iov, &nr_segs, *ppos, | 2369 | written = generic_file_direct_write(iocb, iov, &nr_segs, *ppos, |
2370 | ppos, count, ocount); | 2370 | count, ocount); |
2371 | if (written < 0) { | 2371 | if (written < 0) { |
2372 | ret = written; | 2372 | ret = written; |
2373 | goto out_dio; | 2373 | goto out_dio; |
2374 | } | 2374 | } |
2375 | } else { | 2375 | } else { |
2376 | struct iov_iter from; | ||
2377 | iov_iter_init(&from, iov, nr_segs, count, 0); | ||
2376 | current->backing_dev_info = file->f_mapping->backing_dev_info; | 2378 | current->backing_dev_info = file->f_mapping->backing_dev_info; |
2377 | written = generic_file_buffered_write(iocb, iov, nr_segs, *ppos, | 2379 | written = generic_perform_write(file, &from, *ppos); |
2378 | ppos, count, 0); | 2380 | if (likely(written >= 0)) |
2381 | iocb->ki_pos = *ppos + written; | ||
2379 | current->backing_dev_info = NULL; | 2382 | current->backing_dev_info = NULL; |
2380 | } | 2383 | } |
2381 | 2384 | ||
@@ -655,35 +655,6 @@ out: | |||
655 | return error; | 655 | return error; |
656 | } | 656 | } |
657 | 657 | ||
658 | /* | ||
659 | * You have to be very careful that these write | ||
660 | * counts get cleaned up in error cases and | ||
661 | * upon __fput(). This should probably never | ||
662 | * be called outside of __dentry_open(). | ||
663 | */ | ||
664 | static inline int __get_file_write_access(struct inode *inode, | ||
665 | struct vfsmount *mnt) | ||
666 | { | ||
667 | int error; | ||
668 | error = get_write_access(inode); | ||
669 | if (error) | ||
670 | return error; | ||
671 | /* | ||
672 | * Do not take mount writer counts on | ||
673 | * special files since no writes to | ||
674 | * the mount itself will occur. | ||
675 | */ | ||
676 | if (!special_file(inode->i_mode)) { | ||
677 | /* | ||
678 | * Balanced in __fput() | ||
679 | */ | ||
680 | error = __mnt_want_write(mnt); | ||
681 | if (error) | ||
682 | put_write_access(inode); | ||
683 | } | ||
684 | return error; | ||
685 | } | ||
686 | |||
687 | int open_check_o_direct(struct file *f) | 658 | int open_check_o_direct(struct file *f) |
688 | { | 659 | { |
689 | /* NB: we're sure to have correct a_ops only after f_op->open */ | 660 | /* NB: we're sure to have correct a_ops only after f_op->open */ |
@@ -708,26 +679,28 @@ static int do_dentry_open(struct file *f, | |||
708 | f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK | | 679 | f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK | |
709 | FMODE_PREAD | FMODE_PWRITE; | 680 | FMODE_PREAD | FMODE_PWRITE; |
710 | 681 | ||
711 | if (unlikely(f->f_flags & O_PATH)) | ||
712 | f->f_mode = FMODE_PATH; | ||
713 | |||
714 | path_get(&f->f_path); | 682 | path_get(&f->f_path); |
715 | inode = f->f_inode = f->f_path.dentry->d_inode; | 683 | inode = f->f_inode = f->f_path.dentry->d_inode; |
716 | if (f->f_mode & FMODE_WRITE) { | ||
717 | error = __get_file_write_access(inode, f->f_path.mnt); | ||
718 | if (error) | ||
719 | goto cleanup_file; | ||
720 | if (!special_file(inode->i_mode)) | ||
721 | file_take_write(f); | ||
722 | } | ||
723 | |||
724 | f->f_mapping = inode->i_mapping; | 684 | f->f_mapping = inode->i_mapping; |
725 | 685 | ||
726 | if (unlikely(f->f_mode & FMODE_PATH)) { | 686 | if (unlikely(f->f_flags & O_PATH)) { |
687 | f->f_mode = FMODE_PATH; | ||
727 | f->f_op = &empty_fops; | 688 | f->f_op = &empty_fops; |
728 | return 0; | 689 | return 0; |
729 | } | 690 | } |
730 | 691 | ||
692 | if (f->f_mode & FMODE_WRITE && !special_file(inode->i_mode)) { | ||
693 | error = get_write_access(inode); | ||
694 | if (unlikely(error)) | ||
695 | goto cleanup_file; | ||
696 | error = __mnt_want_write(f->f_path.mnt); | ||
697 | if (unlikely(error)) { | ||
698 | put_write_access(inode); | ||
699 | goto cleanup_file; | ||
700 | } | ||
701 | f->f_mode |= FMODE_WRITER; | ||
702 | } | ||
703 | |||
731 | /* POSIX.1-2008/SUSv4 Section XSI 2.9.7 */ | 704 | /* POSIX.1-2008/SUSv4 Section XSI 2.9.7 */ |
732 | if (S_ISREG(inode->i_mode)) | 705 | if (S_ISREG(inode->i_mode)) |
733 | f->f_mode |= FMODE_ATOMIC_POS; | 706 | f->f_mode |= FMODE_ATOMIC_POS; |
@@ -764,18 +737,9 @@ static int do_dentry_open(struct file *f, | |||
764 | 737 | ||
765 | cleanup_all: | 738 | cleanup_all: |
766 | fops_put(f->f_op); | 739 | fops_put(f->f_op); |
767 | if (f->f_mode & FMODE_WRITE) { | 740 | if (f->f_mode & FMODE_WRITER) { |
768 | put_write_access(inode); | 741 | put_write_access(inode); |
769 | if (!special_file(inode->i_mode)) { | 742 | __mnt_drop_write(f->f_path.mnt); |
770 | /* | ||
771 | * We don't consider this a real | ||
772 | * mnt_want/drop_write() pair | ||
773 | * because it all happenend right | ||
774 | * here, so just reset the state. | ||
775 | */ | ||
776 | file_reset_write(f); | ||
777 | __mnt_drop_write(f->f_path.mnt); | ||
778 | } | ||
779 | } | 743 | } |
780 | cleanup_file: | 744 | cleanup_file: |
781 | path_put(&f->f_path); | 745 | path_put(&f->f_path); |
@@ -142,55 +142,6 @@ pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len, | |||
142 | return 0; | 142 | return 0; |
143 | } | 143 | } |
144 | 144 | ||
145 | static int | ||
146 | pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len, | ||
147 | int atomic) | ||
148 | { | ||
149 | unsigned long copy; | ||
150 | |||
151 | while (len > 0) { | ||
152 | while (!iov->iov_len) | ||
153 | iov++; | ||
154 | copy = min_t(unsigned long, len, iov->iov_len); | ||
155 | |||
156 | if (atomic) { | ||
157 | if (__copy_to_user_inatomic(iov->iov_base, from, copy)) | ||
158 | return -EFAULT; | ||
159 | } else { | ||
160 | if (copy_to_user(iov->iov_base, from, copy)) | ||
161 | return -EFAULT; | ||
162 | } | ||
163 | from += copy; | ||
164 | len -= copy; | ||
165 | iov->iov_base += copy; | ||
166 | iov->iov_len -= copy; | ||
167 | } | ||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | /* | ||
172 | * Attempt to pre-fault in the user memory, so we can use atomic copies. | ||
173 | * Returns the number of bytes not faulted in. | ||
174 | */ | ||
175 | static int iov_fault_in_pages_write(struct iovec *iov, unsigned long len) | ||
176 | { | ||
177 | while (!iov->iov_len) | ||
178 | iov++; | ||
179 | |||
180 | while (len > 0) { | ||
181 | unsigned long this_len; | ||
182 | |||
183 | this_len = min_t(unsigned long, len, iov->iov_len); | ||
184 | if (fault_in_pages_writeable(iov->iov_base, this_len)) | ||
185 | break; | ||
186 | |||
187 | len -= this_len; | ||
188 | iov++; | ||
189 | } | ||
190 | |||
191 | return len; | ||
192 | } | ||
193 | |||
194 | /* | 145 | /* |
195 | * Pre-fault in the user memory, so we can use atomic copies. | 146 | * Pre-fault in the user memory, so we can use atomic copies. |
196 | */ | 147 | */ |
@@ -226,52 +177,6 @@ static void anon_pipe_buf_release(struct pipe_inode_info *pipe, | |||
226 | } | 177 | } |
227 | 178 | ||
228 | /** | 179 | /** |
229 | * generic_pipe_buf_map - virtually map a pipe buffer | ||
230 | * @pipe: the pipe that the buffer belongs to | ||
231 | * @buf: the buffer that should be mapped | ||
232 | * @atomic: whether to use an atomic map | ||
233 | * | ||
234 | * Description: | ||
235 | * This function returns a kernel virtual address mapping for the | ||
236 | * pipe_buffer passed in @buf. If @atomic is set, an atomic map is provided | ||
237 | * and the caller has to be careful not to fault before calling | ||
238 | * the unmap function. | ||
239 | * | ||
240 | * Note that this function calls kmap_atomic() if @atomic != 0. | ||
241 | */ | ||
242 | void *generic_pipe_buf_map(struct pipe_inode_info *pipe, | ||
243 | struct pipe_buffer *buf, int atomic) | ||
244 | { | ||
245 | if (atomic) { | ||
246 | buf->flags |= PIPE_BUF_FLAG_ATOMIC; | ||
247 | return kmap_atomic(buf->page); | ||
248 | } | ||
249 | |||
250 | return kmap(buf->page); | ||
251 | } | ||
252 | EXPORT_SYMBOL(generic_pipe_buf_map); | ||
253 | |||
254 | /** | ||
255 | * generic_pipe_buf_unmap - unmap a previously mapped pipe buffer | ||
256 | * @pipe: the pipe that the buffer belongs to | ||
257 | * @buf: the buffer that should be unmapped | ||
258 | * @map_data: the data that the mapping function returned | ||
259 | * | ||
260 | * Description: | ||
261 | * This function undoes the mapping that ->map() provided. | ||
262 | */ | ||
263 | void generic_pipe_buf_unmap(struct pipe_inode_info *pipe, | ||
264 | struct pipe_buffer *buf, void *map_data) | ||
265 | { | ||
266 | if (buf->flags & PIPE_BUF_FLAG_ATOMIC) { | ||
267 | buf->flags &= ~PIPE_BUF_FLAG_ATOMIC; | ||
268 | kunmap_atomic(map_data); | ||
269 | } else | ||
270 | kunmap(buf->page); | ||
271 | } | ||
272 | EXPORT_SYMBOL(generic_pipe_buf_unmap); | ||
273 | |||
274 | /** | ||
275 | * generic_pipe_buf_steal - attempt to take ownership of a &pipe_buffer | 180 | * generic_pipe_buf_steal - attempt to take ownership of a &pipe_buffer |
276 | * @pipe: the pipe that the buffer belongs to | 181 | * @pipe: the pipe that the buffer belongs to |
277 | * @buf: the buffer to attempt to steal | 182 | * @buf: the buffer to attempt to steal |
@@ -351,8 +256,6 @@ EXPORT_SYMBOL(generic_pipe_buf_release); | |||
351 | 256 | ||
352 | static const struct pipe_buf_operations anon_pipe_buf_ops = { | 257 | static const struct pipe_buf_operations anon_pipe_buf_ops = { |
353 | .can_merge = 1, | 258 | .can_merge = 1, |
354 | .map = generic_pipe_buf_map, | ||
355 | .unmap = generic_pipe_buf_unmap, | ||
356 | .confirm = generic_pipe_buf_confirm, | 259 | .confirm = generic_pipe_buf_confirm, |
357 | .release = anon_pipe_buf_release, | 260 | .release = anon_pipe_buf_release, |
358 | .steal = generic_pipe_buf_steal, | 261 | .steal = generic_pipe_buf_steal, |
@@ -361,8 +264,6 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = { | |||
361 | 264 | ||
362 | static const struct pipe_buf_operations packet_pipe_buf_ops = { | 265 | static const struct pipe_buf_operations packet_pipe_buf_ops = { |
363 | .can_merge = 0, | 266 | .can_merge = 0, |
364 | .map = generic_pipe_buf_map, | ||
365 | .unmap = generic_pipe_buf_unmap, | ||
366 | .confirm = generic_pipe_buf_confirm, | 267 | .confirm = generic_pipe_buf_confirm, |
367 | .release = anon_pipe_buf_release, | 268 | .release = anon_pipe_buf_release, |
368 | .steal = generic_pipe_buf_steal, | 269 | .steal = generic_pipe_buf_steal, |
@@ -379,12 +280,15 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, | |||
379 | ssize_t ret; | 280 | ssize_t ret; |
380 | struct iovec *iov = (struct iovec *)_iov; | 281 | struct iovec *iov = (struct iovec *)_iov; |
381 | size_t total_len; | 282 | size_t total_len; |
283 | struct iov_iter iter; | ||
382 | 284 | ||
383 | total_len = iov_length(iov, nr_segs); | 285 | total_len = iov_length(iov, nr_segs); |
384 | /* Null read succeeds. */ | 286 | /* Null read succeeds. */ |
385 | if (unlikely(total_len == 0)) | 287 | if (unlikely(total_len == 0)) |
386 | return 0; | 288 | return 0; |
387 | 289 | ||
290 | iov_iter_init(&iter, iov, nr_segs, total_len, 0); | ||
291 | |||
388 | do_wakeup = 0; | 292 | do_wakeup = 0; |
389 | ret = 0; | 293 | ret = 0; |
390 | __pipe_lock(pipe); | 294 | __pipe_lock(pipe); |
@@ -394,9 +298,9 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, | |||
394 | int curbuf = pipe->curbuf; | 298 | int curbuf = pipe->curbuf; |
395 | struct pipe_buffer *buf = pipe->bufs + curbuf; | 299 | struct pipe_buffer *buf = pipe->bufs + curbuf; |
396 | const struct pipe_buf_operations *ops = buf->ops; | 300 | const struct pipe_buf_operations *ops = buf->ops; |
397 | void *addr; | ||
398 | size_t chars = buf->len; | 301 | size_t chars = buf->len; |
399 | int error, atomic; | 302 | size_t written; |
303 | int error; | ||
400 | 304 | ||
401 | if (chars > total_len) | 305 | if (chars > total_len) |
402 | chars = total_len; | 306 | chars = total_len; |
@@ -408,21 +312,10 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, | |||
408 | break; | 312 | break; |
409 | } | 313 | } |
410 | 314 | ||
411 | atomic = !iov_fault_in_pages_write(iov, chars); | 315 | written = copy_page_to_iter(buf->page, buf->offset, chars, &iter); |
412 | redo: | 316 | if (unlikely(written < chars)) { |
413 | addr = ops->map(pipe, buf, atomic); | ||
414 | error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars, atomic); | ||
415 | ops->unmap(pipe, buf, addr); | ||
416 | if (unlikely(error)) { | ||
417 | /* | ||
418 | * Just retry with the slow path if we failed. | ||
419 | */ | ||
420 | if (atomic) { | ||
421 | atomic = 0; | ||
422 | goto redo; | ||
423 | } | ||
424 | if (!ret) | 317 | if (!ret) |
425 | ret = error; | 318 | ret = -EFAULT; |
426 | break; | 319 | break; |
427 | } | 320 | } |
428 | ret += chars; | 321 | ret += chars; |
@@ -538,10 +431,16 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov, | |||
538 | 431 | ||
539 | iov_fault_in_pages_read(iov, chars); | 432 | iov_fault_in_pages_read(iov, chars); |
540 | redo1: | 433 | redo1: |
541 | addr = ops->map(pipe, buf, atomic); | 434 | if (atomic) |
435 | addr = kmap_atomic(buf->page); | ||
436 | else | ||
437 | addr = kmap(buf->page); | ||
542 | error = pipe_iov_copy_from_user(offset + addr, iov, | 438 | error = pipe_iov_copy_from_user(offset + addr, iov, |
543 | chars, atomic); | 439 | chars, atomic); |
544 | ops->unmap(pipe, buf, addr); | 440 | if (atomic) |
441 | kunmap_atomic(addr); | ||
442 | else | ||
443 | kunmap(buf->page); | ||
545 | ret = error; | 444 | ret = error; |
546 | do_wakeup = 1; | 445 | do_wakeup = 1; |
547 | if (error) { | 446 | if (error) { |
diff --git a/fs/pnode.c b/fs/pnode.c index 88396df725b4..302bf22c4a30 100644 --- a/fs/pnode.c +++ b/fs/pnode.c | |||
@@ -164,46 +164,94 @@ static struct mount *propagation_next(struct mount *m, | |||
164 | } | 164 | } |
165 | } | 165 | } |
166 | 166 | ||
167 | /* | 167 | static struct mount *next_group(struct mount *m, struct mount *origin) |
168 | * return the source mount to be used for cloning | ||
169 | * | ||
170 | * @dest the current destination mount | ||
171 | * @last_dest the last seen destination mount | ||
172 | * @last_src the last seen source mount | ||
173 | * @type return CL_SLAVE if the new mount has to be | ||
174 | * cloned as a slave. | ||
175 | */ | ||
176 | static struct mount *get_source(struct mount *dest, | ||
177 | struct mount *last_dest, | ||
178 | struct mount *last_src, | ||
179 | int *type) | ||
180 | { | 168 | { |
181 | struct mount *p_last_src = NULL; | 169 | while (1) { |
182 | struct mount *p_last_dest = NULL; | 170 | while (1) { |
183 | 171 | struct mount *next; | |
184 | while (last_dest != dest->mnt_master) { | 172 | if (!IS_MNT_NEW(m) && !list_empty(&m->mnt_slave_list)) |
185 | p_last_dest = last_dest; | 173 | return first_slave(m); |
186 | p_last_src = last_src; | 174 | next = next_peer(m); |
187 | last_dest = last_dest->mnt_master; | 175 | if (m->mnt_group_id == origin->mnt_group_id) { |
188 | last_src = last_src->mnt_master; | 176 | if (next == origin) |
177 | return NULL; | ||
178 | } else if (m->mnt_slave.next != &next->mnt_slave) | ||
179 | break; | ||
180 | m = next; | ||
181 | } | ||
182 | /* m is the last peer */ | ||
183 | while (1) { | ||
184 | struct mount *master = m->mnt_master; | ||
185 | if (m->mnt_slave.next != &master->mnt_slave_list) | ||
186 | return next_slave(m); | ||
187 | m = next_peer(master); | ||
188 | if (master->mnt_group_id == origin->mnt_group_id) | ||
189 | break; | ||
190 | if (master->mnt_slave.next == &m->mnt_slave) | ||
191 | break; | ||
192 | m = master; | ||
193 | } | ||
194 | if (m == origin) | ||
195 | return NULL; | ||
189 | } | 196 | } |
197 | } | ||
190 | 198 | ||
191 | if (p_last_dest) { | 199 | /* all accesses are serialized by namespace_sem */ |
192 | do { | 200 | static struct user_namespace *user_ns; |
193 | p_last_dest = next_peer(p_last_dest); | 201 | static struct mount *last_dest, *last_source, *dest_master; |
194 | } while (IS_MNT_NEW(p_last_dest)); | 202 | static struct mountpoint *mp; |
195 | /* is that a peer of the earlier? */ | 203 | static struct hlist_head *list; |
196 | if (dest == p_last_dest) { | 204 | |
197 | *type = CL_MAKE_SHARED; | 205 | static int propagate_one(struct mount *m) |
198 | return p_last_src; | 206 | { |
207 | struct mount *child; | ||
208 | int type; | ||
209 | /* skip ones added by this propagate_mnt() */ | ||
210 | if (IS_MNT_NEW(m)) | ||
211 | return 0; | ||
212 | /* skip if mountpoint isn't covered by it */ | ||
213 | if (!is_subdir(mp->m_dentry, m->mnt.mnt_root)) | ||
214 | return 0; | ||
215 | if (m->mnt_group_id == last_dest->mnt_group_id) { | ||
216 | type = CL_MAKE_SHARED; | ||
217 | } else { | ||
218 | struct mount *n, *p; | ||
219 | for (n = m; ; n = p) { | ||
220 | p = n->mnt_master; | ||
221 | if (p == dest_master || IS_MNT_MARKED(p)) { | ||
222 | while (last_dest->mnt_master != p) { | ||
223 | last_source = last_source->mnt_master; | ||
224 | last_dest = last_source->mnt_parent; | ||
225 | } | ||
226 | if (n->mnt_group_id != last_dest->mnt_group_id) { | ||
227 | last_source = last_source->mnt_master; | ||
228 | last_dest = last_source->mnt_parent; | ||
229 | } | ||
230 | break; | ||
231 | } | ||
199 | } | 232 | } |
233 | type = CL_SLAVE; | ||
234 | /* beginning of peer group among the slaves? */ | ||
235 | if (IS_MNT_SHARED(m)) | ||
236 | type |= CL_MAKE_SHARED; | ||
200 | } | 237 | } |
201 | /* slave of the earlier, then */ | 238 | |
202 | *type = CL_SLAVE; | 239 | /* Notice when we are propagating across user namespaces */ |
203 | /* beginning of peer group among the slaves? */ | 240 | if (m->mnt_ns->user_ns != user_ns) |
204 | if (IS_MNT_SHARED(dest)) | 241 | type |= CL_UNPRIVILEGED; |
205 | *type |= CL_MAKE_SHARED; | 242 | child = copy_tree(last_source, last_source->mnt.mnt_root, type); |
206 | return last_src; | 243 | if (IS_ERR(child)) |
244 | return PTR_ERR(child); | ||
245 | mnt_set_mountpoint(m, mp, child); | ||
246 | last_dest = m; | ||
247 | last_source = child; | ||
248 | if (m->mnt_master != dest_master) { | ||
249 | read_seqlock_excl(&mount_lock); | ||
250 | SET_MNT_MARK(m->mnt_master); | ||
251 | read_sequnlock_excl(&mount_lock); | ||
252 | } | ||
253 | hlist_add_head(&child->mnt_hash, list); | ||
254 | return 0; | ||
207 | } | 255 | } |
208 | 256 | ||
209 | /* | 257 | /* |
@@ -222,56 +270,48 @@ static struct mount *get_source(struct mount *dest, | |||
222 | int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp, | 270 | int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp, |
223 | struct mount *source_mnt, struct hlist_head *tree_list) | 271 | struct mount *source_mnt, struct hlist_head *tree_list) |
224 | { | 272 | { |
225 | struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns; | 273 | struct mount *m, *n; |
226 | struct mount *m, *child; | ||
227 | int ret = 0; | 274 | int ret = 0; |
228 | struct mount *prev_dest_mnt = dest_mnt; | 275 | |
229 | struct mount *prev_src_mnt = source_mnt; | 276 | /* |
230 | HLIST_HEAD(tmp_list); | 277 | * we don't want to bother passing tons of arguments to |
231 | 278 | * propagate_one(); everything is serialized by namespace_sem, | |
232 | for (m = propagation_next(dest_mnt, dest_mnt); m; | 279 | * so globals will do just fine. |
233 | m = propagation_next(m, dest_mnt)) { | 280 | */ |
234 | int type; | 281 | user_ns = current->nsproxy->mnt_ns->user_ns; |
235 | struct mount *source; | 282 | last_dest = dest_mnt; |
236 | 283 | last_source = source_mnt; | |
237 | if (IS_MNT_NEW(m)) | 284 | mp = dest_mp; |
238 | continue; | 285 | list = tree_list; |
239 | 286 | dest_master = dest_mnt->mnt_master; | |
240 | source = get_source(m, prev_dest_mnt, prev_src_mnt, &type); | 287 | |
241 | 288 | /* all peers of dest_mnt, except dest_mnt itself */ | |
242 | /* Notice when we are propagating across user namespaces */ | 289 | for (n = next_peer(dest_mnt); n != dest_mnt; n = next_peer(n)) { |
243 | if (m->mnt_ns->user_ns != user_ns) | 290 | ret = propagate_one(n); |
244 | type |= CL_UNPRIVILEGED; | 291 | if (ret) |
245 | |||
246 | child = copy_tree(source, source->mnt.mnt_root, type); | ||
247 | if (IS_ERR(child)) { | ||
248 | ret = PTR_ERR(child); | ||
249 | tmp_list = *tree_list; | ||
250 | tmp_list.first->pprev = &tmp_list.first; | ||
251 | INIT_HLIST_HEAD(tree_list); | ||
252 | goto out; | 292 | goto out; |
253 | } | 293 | } |
254 | 294 | ||
255 | if (is_subdir(dest_mp->m_dentry, m->mnt.mnt_root)) { | 295 | /* all slave groups */ |
256 | mnt_set_mountpoint(m, dest_mp, child); | 296 | for (m = next_group(dest_mnt, dest_mnt); m; |
257 | hlist_add_head(&child->mnt_hash, tree_list); | 297 | m = next_group(m, dest_mnt)) { |
258 | } else { | 298 | /* everything in that slave group */ |
259 | /* | 299 | n = m; |
260 | * This can happen if the parent mount was bind mounted | 300 | do { |
261 | * on some subdirectory of a shared/slave mount. | 301 | ret = propagate_one(n); |
262 | */ | 302 | if (ret) |
263 | hlist_add_head(&child->mnt_hash, &tmp_list); | 303 | goto out; |
264 | } | 304 | n = next_peer(n); |
265 | prev_dest_mnt = m; | 305 | } while (n != m); |
266 | prev_src_mnt = child; | ||
267 | } | 306 | } |
268 | out: | 307 | out: |
269 | lock_mount_hash(); | 308 | read_seqlock_excl(&mount_lock); |
270 | while (!hlist_empty(&tmp_list)) { | 309 | hlist_for_each_entry(n, tree_list, mnt_hash) { |
271 | child = hlist_entry(tmp_list.first, struct mount, mnt_hash); | 310 | m = n->mnt_parent; |
272 | umount_tree(child, 0); | 311 | if (m->mnt_master != dest_mnt->mnt_master) |
312 | CLEAR_MNT_MARK(m->mnt_master); | ||
273 | } | 313 | } |
274 | unlock_mount_hash(); | 314 | read_sequnlock_excl(&mount_lock); |
275 | return ret; | 315 | return ret; |
276 | } | 316 | } |
277 | 317 | ||
diff --git a/fs/pnode.h b/fs/pnode.h index fc28a27fa892..4a246358b031 100644 --- a/fs/pnode.h +++ b/fs/pnode.h | |||
@@ -16,6 +16,9 @@ | |||
16 | #define IS_MNT_NEW(m) (!(m)->mnt_ns) | 16 | #define IS_MNT_NEW(m) (!(m)->mnt_ns) |
17 | #define CLEAR_MNT_SHARED(m) ((m)->mnt.mnt_flags &= ~MNT_SHARED) | 17 | #define CLEAR_MNT_SHARED(m) ((m)->mnt.mnt_flags &= ~MNT_SHARED) |
18 | #define IS_MNT_UNBINDABLE(m) ((m)->mnt.mnt_flags & MNT_UNBINDABLE) | 18 | #define IS_MNT_UNBINDABLE(m) ((m)->mnt.mnt_flags & MNT_UNBINDABLE) |
19 | #define IS_MNT_MARKED(m) ((m)->mnt.mnt_flags & MNT_MARKED) | ||
20 | #define SET_MNT_MARK(m) ((m)->mnt.mnt_flags |= MNT_MARKED) | ||
21 | #define CLEAR_MNT_MARK(m) ((m)->mnt.mnt_flags &= ~MNT_MARKED) | ||
19 | 22 | ||
20 | #define CL_EXPIRE 0x01 | 23 | #define CL_EXPIRE 0x01 |
21 | #define CL_SLAVE 0x02 | 24 | #define CL_SLAVE 0x02 |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 6b7087e2e8fb..2d696b0c93bf 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -200,41 +200,9 @@ static int proc_root_link(struct dentry *dentry, struct path *path) | |||
200 | return result; | 200 | return result; |
201 | } | 201 | } |
202 | 202 | ||
203 | static int proc_pid_cmdline(struct task_struct *task, char * buffer) | 203 | static int proc_pid_cmdline(struct task_struct *task, char *buffer) |
204 | { | 204 | { |
205 | int res = 0; | 205 | return get_cmdline(task, buffer, PAGE_SIZE); |
206 | unsigned int len; | ||
207 | struct mm_struct *mm = get_task_mm(task); | ||
208 | if (!mm) | ||
209 | goto out; | ||
210 | if (!mm->arg_end) | ||
211 | goto out_mm; /* Shh! No looking before we're done */ | ||
212 | |||
213 | len = mm->arg_end - mm->arg_start; | ||
214 | |||
215 | if (len > PAGE_SIZE) | ||
216 | len = PAGE_SIZE; | ||
217 | |||
218 | res = access_process_vm(task, mm->arg_start, buffer, len, 0); | ||
219 | |||
220 | // If the nul at the end of args has been overwritten, then | ||
221 | // assume application is using setproctitle(3). | ||
222 | if (res > 0 && buffer[res-1] != '\0' && len < PAGE_SIZE) { | ||
223 | len = strnlen(buffer, res); | ||
224 | if (len < res) { | ||
225 | res = len; | ||
226 | } else { | ||
227 | len = mm->env_end - mm->env_start; | ||
228 | if (len > PAGE_SIZE - res) | ||
229 | len = PAGE_SIZE - res; | ||
230 | res += access_process_vm(task, mm->env_start, buffer+res, len, 0); | ||
231 | res = strnlen(buffer, res); | ||
232 | } | ||
233 | } | ||
234 | out_mm: | ||
235 | mmput(mm); | ||
236 | out: | ||
237 | return res; | ||
238 | } | 206 | } |
239 | 207 | ||
240 | static int proc_pid_auxv(struct task_struct *task, char *buffer) | 208 | static int proc_pid_auxv(struct task_struct *task, char *buffer) |
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c index 9ae46b87470d..89026095f2b5 100644 --- a/fs/proc/namespaces.c +++ b/fs/proc/namespaces.c | |||
@@ -146,7 +146,7 @@ static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int bufl | |||
146 | struct task_struct *task; | 146 | struct task_struct *task; |
147 | void *ns; | 147 | void *ns; |
148 | char name[50]; | 148 | char name[50]; |
149 | int len = -EACCES; | 149 | int res = -EACCES; |
150 | 150 | ||
151 | task = get_proc_task(inode); | 151 | task = get_proc_task(inode); |
152 | if (!task) | 152 | if (!task) |
@@ -155,24 +155,18 @@ static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int bufl | |||
155 | if (!ptrace_may_access(task, PTRACE_MODE_READ)) | 155 | if (!ptrace_may_access(task, PTRACE_MODE_READ)) |
156 | goto out_put_task; | 156 | goto out_put_task; |
157 | 157 | ||
158 | len = -ENOENT; | 158 | res = -ENOENT; |
159 | ns = ns_ops->get(task); | 159 | ns = ns_ops->get(task); |
160 | if (!ns) | 160 | if (!ns) |
161 | goto out_put_task; | 161 | goto out_put_task; |
162 | 162 | ||
163 | snprintf(name, sizeof(name), "%s:[%u]", ns_ops->name, ns_ops->inum(ns)); | 163 | snprintf(name, sizeof(name), "%s:[%u]", ns_ops->name, ns_ops->inum(ns)); |
164 | len = strlen(name); | 164 | res = readlink_copy(buffer, buflen, name); |
165 | |||
166 | if (len > buflen) | ||
167 | len = buflen; | ||
168 | if (copy_to_user(buffer, name, len)) | ||
169 | len = -EFAULT; | ||
170 | |||
171 | ns_ops->put(ns); | 165 | ns_ops->put(ns); |
172 | out_put_task: | 166 | out_put_task: |
173 | put_task_struct(task); | 167 | put_task_struct(task); |
174 | out: | 168 | out: |
175 | return len; | 169 | return res; |
176 | } | 170 | } |
177 | 171 | ||
178 | static const struct inode_operations proc_ns_link_inode_operations = { | 172 | static const struct inode_operations proc_ns_link_inode_operations = { |
diff --git a/fs/proc/self.c b/fs/proc/self.c index ffeb202ec942..4348bb8907c2 100644 --- a/fs/proc/self.c +++ b/fs/proc/self.c | |||
@@ -16,7 +16,7 @@ static int proc_self_readlink(struct dentry *dentry, char __user *buffer, | |||
16 | if (!tgid) | 16 | if (!tgid) |
17 | return -ENOENT; | 17 | return -ENOENT; |
18 | sprintf(tmp, "%d", tgid); | 18 | sprintf(tmp, "%d", tgid); |
19 | return vfs_readlink(dentry,buffer,buflen,tmp); | 19 | return readlink_copy(buffer, buflen, tmp); |
20 | } | 20 | } |
21 | 21 | ||
22 | static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) | 22 | static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) |
diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c index 7be26f03a3f5..1a81373947f3 100644 --- a/fs/proc_namespace.c +++ b/fs/proc_namespace.c | |||
@@ -267,6 +267,7 @@ static int mounts_open_common(struct inode *inode, struct file *file, | |||
267 | p->root = root; | 267 | p->root = root; |
268 | p->m.poll_event = ns->event; | 268 | p->m.poll_event = ns->event; |
269 | p->show = show; | 269 | p->show = show; |
270 | p->cached_event = ~0ULL; | ||
270 | 271 | ||
271 | return 0; | 272 | return 0; |
272 | 273 | ||
diff --git a/fs/splice.c b/fs/splice.c index 12028fa41def..9bc07d2b53cf 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -136,8 +136,6 @@ error: | |||
136 | 136 | ||
137 | const struct pipe_buf_operations page_cache_pipe_buf_ops = { | 137 | const struct pipe_buf_operations page_cache_pipe_buf_ops = { |
138 | .can_merge = 0, | 138 | .can_merge = 0, |
139 | .map = generic_pipe_buf_map, | ||
140 | .unmap = generic_pipe_buf_unmap, | ||
141 | .confirm = page_cache_pipe_buf_confirm, | 139 | .confirm = page_cache_pipe_buf_confirm, |
142 | .release = page_cache_pipe_buf_release, | 140 | .release = page_cache_pipe_buf_release, |
143 | .steal = page_cache_pipe_buf_steal, | 141 | .steal = page_cache_pipe_buf_steal, |
@@ -156,8 +154,6 @@ static int user_page_pipe_buf_steal(struct pipe_inode_info *pipe, | |||
156 | 154 | ||
157 | static const struct pipe_buf_operations user_page_pipe_buf_ops = { | 155 | static const struct pipe_buf_operations user_page_pipe_buf_ops = { |
158 | .can_merge = 0, | 156 | .can_merge = 0, |
159 | .map = generic_pipe_buf_map, | ||
160 | .unmap = generic_pipe_buf_unmap, | ||
161 | .confirm = generic_pipe_buf_confirm, | 157 | .confirm = generic_pipe_buf_confirm, |
162 | .release = page_cache_pipe_buf_release, | 158 | .release = page_cache_pipe_buf_release, |
163 | .steal = user_page_pipe_buf_steal, | 159 | .steal = user_page_pipe_buf_steal, |
@@ -547,8 +543,6 @@ EXPORT_SYMBOL(generic_file_splice_read); | |||
547 | 543 | ||
548 | static const struct pipe_buf_operations default_pipe_buf_ops = { | 544 | static const struct pipe_buf_operations default_pipe_buf_ops = { |
549 | .can_merge = 0, | 545 | .can_merge = 0, |
550 | .map = generic_pipe_buf_map, | ||
551 | .unmap = generic_pipe_buf_unmap, | ||
552 | .confirm = generic_pipe_buf_confirm, | 546 | .confirm = generic_pipe_buf_confirm, |
553 | .release = generic_pipe_buf_release, | 547 | .release = generic_pipe_buf_release, |
554 | .steal = generic_pipe_buf_steal, | 548 | .steal = generic_pipe_buf_steal, |
@@ -564,8 +558,6 @@ static int generic_pipe_buf_nosteal(struct pipe_inode_info *pipe, | |||
564 | /* Pipe buffer operations for a socket and similar. */ | 558 | /* Pipe buffer operations for a socket and similar. */ |
565 | const struct pipe_buf_operations nosteal_pipe_buf_ops = { | 559 | const struct pipe_buf_operations nosteal_pipe_buf_ops = { |
566 | .can_merge = 0, | 560 | .can_merge = 0, |
567 | .map = generic_pipe_buf_map, | ||
568 | .unmap = generic_pipe_buf_unmap, | ||
569 | .confirm = generic_pipe_buf_confirm, | 561 | .confirm = generic_pipe_buf_confirm, |
570 | .release = generic_pipe_buf_release, | 562 | .release = generic_pipe_buf_release, |
571 | .steal = generic_pipe_buf_nosteal, | 563 | .steal = generic_pipe_buf_nosteal, |
@@ -767,13 +759,13 @@ int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf, | |||
767 | goto out; | 759 | goto out; |
768 | 760 | ||
769 | if (buf->page != page) { | 761 | if (buf->page != page) { |
770 | char *src = buf->ops->map(pipe, buf, 1); | 762 | char *src = kmap_atomic(buf->page); |
771 | char *dst = kmap_atomic(page); | 763 | char *dst = kmap_atomic(page); |
772 | 764 | ||
773 | memcpy(dst + offset, src + buf->offset, this_len); | 765 | memcpy(dst + offset, src + buf->offset, this_len); |
774 | flush_dcache_page(page); | 766 | flush_dcache_page(page); |
775 | kunmap_atomic(dst); | 767 | kunmap_atomic(dst); |
776 | buf->ops->unmap(pipe, buf, src); | 768 | kunmap_atomic(src); |
777 | } | 769 | } |
778 | ret = pagecache_write_end(file, mapping, sd->pos, this_len, this_len, | 770 | ret = pagecache_write_end(file, mapping, sd->pos, this_len, this_len, |
779 | page, fsdata); | 771 | page, fsdata); |
@@ -1067,9 +1059,9 @@ static int write_pipe_buf(struct pipe_inode_info *pipe, struct pipe_buffer *buf, | |||
1067 | void *data; | 1059 | void *data; |
1068 | loff_t tmp = sd->pos; | 1060 | loff_t tmp = sd->pos; |
1069 | 1061 | ||
1070 | data = buf->ops->map(pipe, buf, 0); | 1062 | data = kmap(buf->page); |
1071 | ret = __kernel_write(sd->u.file, data + buf->offset, sd->len, &tmp); | 1063 | ret = __kernel_write(sd->u.file, data + buf->offset, sd->len, &tmp); |
1072 | buf->ops->unmap(pipe, buf, data); | 1064 | kunmap(buf->page); |
1073 | 1065 | ||
1074 | return ret; | 1066 | return ret; |
1075 | } | 1067 | } |
@@ -1528,116 +1520,48 @@ static int get_iovec_page_array(const struct iovec __user *iov, | |||
1528 | static int pipe_to_user(struct pipe_inode_info *pipe, struct pipe_buffer *buf, | 1520 | static int pipe_to_user(struct pipe_inode_info *pipe, struct pipe_buffer *buf, |
1529 | struct splice_desc *sd) | 1521 | struct splice_desc *sd) |
1530 | { | 1522 | { |
1531 | char *src; | 1523 | int n = copy_page_to_iter(buf->page, buf->offset, sd->len, sd->u.data); |
1532 | int ret; | 1524 | return n == sd->len ? n : -EFAULT; |
1533 | |||
1534 | /* | ||
1535 | * See if we can use the atomic maps, by prefaulting in the | ||
1536 | * pages and doing an atomic copy | ||
1537 | */ | ||
1538 | if (!fault_in_pages_writeable(sd->u.userptr, sd->len)) { | ||
1539 | src = buf->ops->map(pipe, buf, 1); | ||
1540 | ret = __copy_to_user_inatomic(sd->u.userptr, src + buf->offset, | ||
1541 | sd->len); | ||
1542 | buf->ops->unmap(pipe, buf, src); | ||
1543 | if (!ret) { | ||
1544 | ret = sd->len; | ||
1545 | goto out; | ||
1546 | } | ||
1547 | } | ||
1548 | |||
1549 | /* | ||
1550 | * No dice, use slow non-atomic map and copy | ||
1551 | */ | ||
1552 | src = buf->ops->map(pipe, buf, 0); | ||
1553 | |||
1554 | ret = sd->len; | ||
1555 | if (copy_to_user(sd->u.userptr, src + buf->offset, sd->len)) | ||
1556 | ret = -EFAULT; | ||
1557 | |||
1558 | buf->ops->unmap(pipe, buf, src); | ||
1559 | out: | ||
1560 | if (ret > 0) | ||
1561 | sd->u.userptr += ret; | ||
1562 | return ret; | ||
1563 | } | 1525 | } |
1564 | 1526 | ||
1565 | /* | 1527 | /* |
1566 | * For lack of a better implementation, implement vmsplice() to userspace | 1528 | * For lack of a better implementation, implement vmsplice() to userspace |
1567 | * as a simple copy of the pipes pages to the user iov. | 1529 | * as a simple copy of the pipes pages to the user iov. |
1568 | */ | 1530 | */ |
1569 | static long vmsplice_to_user(struct file *file, const struct iovec __user *iov, | 1531 | static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov, |
1570 | unsigned long nr_segs, unsigned int flags) | 1532 | unsigned long nr_segs, unsigned int flags) |
1571 | { | 1533 | { |
1572 | struct pipe_inode_info *pipe; | 1534 | struct pipe_inode_info *pipe; |
1573 | struct splice_desc sd; | 1535 | struct splice_desc sd; |
1574 | ssize_t size; | ||
1575 | int error; | ||
1576 | long ret; | 1536 | long ret; |
1537 | struct iovec iovstack[UIO_FASTIOV]; | ||
1538 | struct iovec *iov = iovstack; | ||
1539 | struct iov_iter iter; | ||
1540 | ssize_t count = 0; | ||
1577 | 1541 | ||
1578 | pipe = get_pipe_info(file); | 1542 | pipe = get_pipe_info(file); |
1579 | if (!pipe) | 1543 | if (!pipe) |
1580 | return -EBADF; | 1544 | return -EBADF; |
1581 | 1545 | ||
1582 | pipe_lock(pipe); | 1546 | ret = rw_copy_check_uvector(READ, uiov, nr_segs, |
1583 | 1547 | ARRAY_SIZE(iovstack), iovstack, &iov); | |
1584 | error = ret = 0; | 1548 | if (ret <= 0) |
1585 | while (nr_segs) { | 1549 | return ret; |
1586 | void __user *base; | ||
1587 | size_t len; | ||
1588 | |||
1589 | /* | ||
1590 | * Get user address base and length for this iovec. | ||
1591 | */ | ||
1592 | error = get_user(base, &iov->iov_base); | ||
1593 | if (unlikely(error)) | ||
1594 | break; | ||
1595 | error = get_user(len, &iov->iov_len); | ||
1596 | if (unlikely(error)) | ||
1597 | break; | ||
1598 | |||
1599 | /* | ||
1600 | * Sanity check this iovec. 0 read succeeds. | ||
1601 | */ | ||
1602 | if (unlikely(!len)) | ||
1603 | break; | ||
1604 | if (unlikely(!base)) { | ||
1605 | error = -EFAULT; | ||
1606 | break; | ||
1607 | } | ||
1608 | |||
1609 | if (unlikely(!access_ok(VERIFY_WRITE, base, len))) { | ||
1610 | error = -EFAULT; | ||
1611 | break; | ||
1612 | } | ||
1613 | |||
1614 | sd.len = 0; | ||
1615 | sd.total_len = len; | ||
1616 | sd.flags = flags; | ||
1617 | sd.u.userptr = base; | ||
1618 | sd.pos = 0; | ||
1619 | |||
1620 | size = __splice_from_pipe(pipe, &sd, pipe_to_user); | ||
1621 | if (size < 0) { | ||
1622 | if (!ret) | ||
1623 | ret = size; | ||
1624 | |||
1625 | break; | ||
1626 | } | ||
1627 | |||
1628 | ret += size; | ||
1629 | 1550 | ||
1630 | if (size < len) | 1551 | iov_iter_init(&iter, iov, nr_segs, count, 0); |
1631 | break; | ||
1632 | 1552 | ||
1633 | nr_segs--; | 1553 | sd.len = 0; |
1634 | iov++; | 1554 | sd.total_len = count; |
1635 | } | 1555 | sd.flags = flags; |
1556 | sd.u.data = &iter; | ||
1557 | sd.pos = 0; | ||
1636 | 1558 | ||
1559 | pipe_lock(pipe); | ||
1560 | ret = __splice_from_pipe(pipe, &sd, pipe_to_user); | ||
1637 | pipe_unlock(pipe); | 1561 | pipe_unlock(pipe); |
1638 | 1562 | ||
1639 | if (!ret) | 1563 | if (iov != iovstack) |
1640 | ret = error; | 1564 | kfree(iov); |
1641 | 1565 | ||
1642 | return ret; | 1566 | return ret; |
1643 | } | 1567 | } |
diff --git a/fs/udf/file.c b/fs/udf/file.c index 1037637957c7..d2c170f8b035 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c | |||
@@ -171,7 +171,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
171 | } else | 171 | } else |
172 | up_write(&iinfo->i_data_sem); | 172 | up_write(&iinfo->i_data_sem); |
173 | 173 | ||
174 | retval = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); | 174 | retval = __generic_file_aio_write(iocb, iov, nr_segs); |
175 | mutex_unlock(&inode->i_mutex); | 175 | mutex_unlock(&inode->i_mutex); |
176 | 176 | ||
177 | if (retval > 0) { | 177 | if (retval > 0) { |
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 003c0051b62f..79e96ce98733 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -699,7 +699,7 @@ xfs_file_dio_aio_write( | |||
699 | 699 | ||
700 | trace_xfs_file_direct_write(ip, count, iocb->ki_pos, 0); | 700 | trace_xfs_file_direct_write(ip, count, iocb->ki_pos, 0); |
701 | ret = generic_file_direct_write(iocb, iovp, | 701 | ret = generic_file_direct_write(iocb, iovp, |
702 | &nr_segs, pos, &iocb->ki_pos, count, ocount); | 702 | &nr_segs, pos, count, ocount); |
703 | 703 | ||
704 | out: | 704 | out: |
705 | xfs_rw_iunlock(ip, iolock); | 705 | xfs_rw_iunlock(ip, iolock); |
@@ -715,7 +715,7 @@ xfs_file_buffered_aio_write( | |||
715 | const struct iovec *iovp, | 715 | const struct iovec *iovp, |
716 | unsigned long nr_segs, | 716 | unsigned long nr_segs, |
717 | loff_t pos, | 717 | loff_t pos, |
718 | size_t ocount) | 718 | size_t count) |
719 | { | 719 | { |
720 | struct file *file = iocb->ki_filp; | 720 | struct file *file = iocb->ki_filp; |
721 | struct address_space *mapping = file->f_mapping; | 721 | struct address_space *mapping = file->f_mapping; |
@@ -724,7 +724,7 @@ xfs_file_buffered_aio_write( | |||
724 | ssize_t ret; | 724 | ssize_t ret; |
725 | int enospc = 0; | 725 | int enospc = 0; |
726 | int iolock = XFS_IOLOCK_EXCL; | 726 | int iolock = XFS_IOLOCK_EXCL; |
727 | size_t count = ocount; | 727 | struct iov_iter from; |
728 | 728 | ||
729 | xfs_rw_ilock(ip, iolock); | 729 | xfs_rw_ilock(ip, iolock); |
730 | 730 | ||
@@ -732,14 +732,15 @@ xfs_file_buffered_aio_write( | |||
732 | if (ret) | 732 | if (ret) |
733 | goto out; | 733 | goto out; |
734 | 734 | ||
735 | iov_iter_init(&from, iovp, nr_segs, count, 0); | ||
735 | /* We can write back this queue in page reclaim */ | 736 | /* We can write back this queue in page reclaim */ |
736 | current->backing_dev_info = mapping->backing_dev_info; | 737 | current->backing_dev_info = mapping->backing_dev_info; |
737 | 738 | ||
738 | write_retry: | 739 | write_retry: |
739 | trace_xfs_file_buffered_write(ip, count, iocb->ki_pos, 0); | 740 | trace_xfs_file_buffered_write(ip, count, iocb->ki_pos, 0); |
740 | ret = generic_file_buffered_write(iocb, iovp, nr_segs, | 741 | ret = generic_perform_write(file, &from, pos); |
741 | pos, &iocb->ki_pos, count, 0); | 742 | if (likely(ret >= 0)) |
742 | 743 | iocb->ki_pos = pos + ret; | |
743 | /* | 744 | /* |
744 | * If we just got an ENOSPC, try to write back all dirty inodes to | 745 | * If we just got an ENOSPC, try to write back all dirty inodes to |
745 | * convert delalloc space to free up some of the excess reserved | 746 | * convert delalloc space to free up some of the excess reserved |
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index bcfe61202115..0b18776b075e 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c | |||
@@ -271,32 +271,6 @@ xfs_open_by_handle( | |||
271 | return error; | 271 | return error; |
272 | } | 272 | } |
273 | 273 | ||
274 | /* | ||
275 | * This is a copy from fs/namei.c:vfs_readlink(), except for removing it's | ||
276 | * unused first argument. | ||
277 | */ | ||
278 | STATIC int | ||
279 | do_readlink( | ||
280 | char __user *buffer, | ||
281 | int buflen, | ||
282 | const char *link) | ||
283 | { | ||
284 | int len; | ||
285 | |||
286 | len = PTR_ERR(link); | ||
287 | if (IS_ERR(link)) | ||
288 | goto out; | ||
289 | |||
290 | len = strlen(link); | ||
291 | if (len > (unsigned) buflen) | ||
292 | len = buflen; | ||
293 | if (copy_to_user(buffer, link, len)) | ||
294 | len = -EFAULT; | ||
295 | out: | ||
296 | return len; | ||
297 | } | ||
298 | |||
299 | |||
300 | int | 274 | int |
301 | xfs_readlink_by_handle( | 275 | xfs_readlink_by_handle( |
302 | struct file *parfilp, | 276 | struct file *parfilp, |
@@ -334,7 +308,7 @@ xfs_readlink_by_handle( | |||
334 | error = -xfs_readlink(XFS_I(dentry->d_inode), link); | 308 | error = -xfs_readlink(XFS_I(dentry->d_inode), link); |
335 | if (error) | 309 | if (error) |
336 | goto out_kfree; | 310 | goto out_kfree; |
337 | error = do_readlink(hreq->ohandle, olen, link); | 311 | error = readlink_copy(hreq->ohandle, olen, link); |
338 | if (error) | 312 | if (error) |
339 | goto out_kfree; | 313 | goto out_kfree; |
340 | 314 | ||