From: Greg Kroah-Hartman Date: Wed, 5 Mar 2014 18:34:52 +0000 (-0800) Subject: 3.4-stable patches X-Git-Tag: v3.10.33~5 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6b5a1c7c378e1fa56b31c7e0d83ced654a677fe9;p=thirdparty%2Fkernel%2Fstable-queue.git 3.4-stable patches added patches: fuse-hotfix-truncate_pagecache-issue.patch fuse-readdir-check-for-slash-in-names.patch libceph-unregister-request-in-__map_request-failed-and-nofail-false.patch nilfs2-fix-issue-with-race-condition-of-competition-between-segments-for-dirty-blocks.patch --- diff --git a/queue-3.4/fuse-hotfix-truncate_pagecache-issue.patch b/queue-3.4/fuse-hotfix-truncate_pagecache-issue.patch new file mode 100644 index 00000000000..0c549675873 --- /dev/null +++ b/queue-3.4/fuse-hotfix-truncate_pagecache-issue.patch @@ -0,0 +1,194 @@ +From 9417815157557d273325641f7ad2b6dd147276f4 Mon Sep 17 00:00:00 2001 +From: Maxim Patlasov +Date: Fri, 30 Aug 2013 17:06:04 +0400 +Subject: fuse: hotfix truncate_pagecache() issue + +From: Maxim Patlasov + +commit 06a7c3c2781409af95000c60a5df743fd4e2f8b4 upstream. + +The way how fuse calls truncate_pagecache() from fuse_change_attributes() +is completely wrong. Because, w/o i_mutex held, we never sure whether +'oldsize' and 'attr->size' are valid by the time of execution of +truncate_pagecache(inode, oldsize, attr->size). In fact, as soon as we +released fc->lock in the middle of fuse_change_attributes(), we completely +loose control of actions which may happen with given inode until we reach +truncate_pagecache. The list of potentially dangerous actions includes +mmap-ed reads and writes, ftruncate(2) and write(2) extending file size. + +The typical outcome of doing truncate_pagecache() with outdated arguments +is data corruption from user point of view. This is (in some sense) +acceptable in cases when the issue is triggered by a change of the file on +the server (i.e. externally wrt fuse operation), but it is absolutely +intolerable in scenarios when a single fuse client modifies a file without +any external intervention. A real life case I discovered by fsx-linux +looked like this: + +1. Shrinking ftruncate(2) comes to fuse_do_setattr(). The latter sends +FUSE_SETATTR to the server synchronously, but before getting fc->lock ... +2. fuse_dentry_revalidate() is asynchronously called. It sends FUSE_LOOKUP +to the server synchronously, then calls fuse_change_attributes(). The +latter updates i_size, releases fc->lock, but before comparing oldsize vs +attr->size.. +3. fuse_do_setattr() from the first step proceeds by acquiring fc->lock and +updating attributes and i_size, but now oldsize is equal to +outarg.attr.size because i_size has just been updated (step 2). Hence, +fuse_do_setattr() returns w/o calling truncate_pagecache(). +4. As soon as ftruncate(2) completes, the user extends file size by +write(2) making a hole in the middle of file, then reads data from the hole +either by read(2) or mmap-ed read. The user expects to get zero data from +the hole, but gets stale data because truncate_pagecache() is not executed +yet. + +The scenario above illustrates one side of the problem: not truncating the +page cache even though we should. Another side corresponds to truncating +page cache too late, when the state of inode changed significantly. +Theoretically, the following is possible: + +1. As in the previous scenario fuse_dentry_revalidate() discovered that +i_size changed (due to our own fuse_do_setattr()) and is going to call +truncate_pagecache() for some 'new_size' it believes valid right now. But +by the time that particular truncate_pagecache() is called ... +2. fuse_do_setattr() returns (either having called truncate_pagecache() or +not -- it doesn't matter). +3. The file is extended either by write(2) or ftruncate(2) or fallocate(2). +4. mmap-ed write makes a page in the extended region dirty. + +The result will be the lost of data user wrote on the fourth step. + +The patch is a hotfix resolving the issue in a simplistic way: let's skip +dangerous i_size update and truncate_pagecache if an operation changing +file size is in progress. This simplistic approach looks correct for the +cases w/o external changes. And to handle them properly, more sophisticated +and intrusive techniques (e.g. NFS-like one) would be required. I'd like to +postpone it until the issue is well discussed on the mailing list(s). + +Changed in v2: + - improved patch description to cover both sides of the issue. + +Signed-off-by: Maxim Patlasov +Signed-off-by: Miklos Szeredi +[bwh: Backported to 3.2: add the fuse_inode::state field which we didn't have] +Signed-off-by: Ben Hutchings +Cc: Rui Xiang +Signed-off-by: Greg Kroah-Hartman + +--- + fs/fuse/dir.c | 7 ++++++- + fs/fuse/file.c | 8 +++++++- + fs/fuse/fuse_i.h | 9 +++++++++ + fs/fuse/inode.c | 4 +++- + 4 files changed, 25 insertions(+), 3 deletions(-) + +--- a/fs/fuse/dir.c ++++ b/fs/fuse/dir.c +@@ -1348,6 +1348,7 @@ static int fuse_do_setattr(struct dentry + { + struct inode *inode = entry->d_inode; + struct fuse_conn *fc = get_fuse_conn(inode); ++ struct fuse_inode *fi = get_fuse_inode(inode); + struct fuse_req *req; + struct fuse_setattr_in inarg; + struct fuse_attr_out outarg; +@@ -1378,8 +1379,10 @@ static int fuse_do_setattr(struct dentry + if (IS_ERR(req)) + return PTR_ERR(req); + +- if (is_truncate) ++ if (is_truncate) { + fuse_set_nowrite(inode); ++ set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); ++ } + + memset(&inarg, 0, sizeof(inarg)); + memset(&outarg, 0, sizeof(outarg)); +@@ -1441,12 +1444,14 @@ static int fuse_do_setattr(struct dentry + invalidate_inode_pages2(inode->i_mapping); + } + ++ clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); + return 0; + + error: + if (is_truncate) + fuse_release_nowrite(inode); + ++ clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); + return err; + } + +--- a/fs/fuse/file.c ++++ b/fs/fuse/file.c +@@ -515,7 +515,8 @@ static void fuse_read_update_size(struct + struct fuse_inode *fi = get_fuse_inode(inode); + + spin_lock(&fc->lock); +- if (attr_ver == fi->attr_version && size < inode->i_size) { ++ if (attr_ver == fi->attr_version && size < inode->i_size && ++ !test_bit(FUSE_I_SIZE_UNSTABLE, &fi->state)) { + fi->attr_version = ++fc->attr_version; + i_size_write(inode, size); + } +@@ -877,12 +878,16 @@ static ssize_t fuse_perform_write(struct + { + struct inode *inode = mapping->host; + struct fuse_conn *fc = get_fuse_conn(inode); ++ struct fuse_inode *fi = get_fuse_inode(inode); + int err = 0; + ssize_t res = 0; + + if (is_bad_inode(inode)) + return -EIO; + ++ if (inode->i_size < pos + iov_iter_count(ii)) ++ set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); ++ + do { + struct fuse_req *req; + ssize_t count; +@@ -917,6 +922,7 @@ static ssize_t fuse_perform_write(struct + if (res > 0) + fuse_write_update_size(inode, pos); + ++ clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); + fuse_invalidate_attr(inode); + + return res > 0 ? res : err; +--- a/fs/fuse/fuse_i.h ++++ b/fs/fuse/fuse_i.h +@@ -103,6 +103,15 @@ struct fuse_inode { + + /** List of writepage requestst (pending or sent) */ + struct list_head writepages; ++ ++ /** Miscellaneous bits describing inode state */ ++ unsigned long state; ++}; ++ ++/** FUSE inode state bits */ ++enum { ++ /** An operation changing file size is in progress */ ++ FUSE_I_SIZE_UNSTABLE, + }; + + struct fuse_conn; +--- a/fs/fuse/inode.c ++++ b/fs/fuse/inode.c +@@ -92,6 +92,7 @@ static struct inode *fuse_alloc_inode(st + fi->attr_version = 0; + fi->writectr = 0; + fi->orig_ino = 0; ++ fi->state = 0; + INIT_LIST_HEAD(&fi->write_files); + INIT_LIST_HEAD(&fi->queued_writes); + INIT_LIST_HEAD(&fi->writepages); +@@ -199,7 +200,8 @@ void fuse_change_attributes(struct inode + loff_t oldsize; + + spin_lock(&fc->lock); +- if (attr_version != 0 && fi->attr_version > attr_version) { ++ if ((attr_version != 0 && fi->attr_version > attr_version) || ++ test_bit(FUSE_I_SIZE_UNSTABLE, &fi->state)) { + spin_unlock(&fc->lock); + return; + } diff --git a/queue-3.4/fuse-readdir-check-for-slash-in-names.patch b/queue-3.4/fuse-readdir-check-for-slash-in-names.patch new file mode 100644 index 00000000000..a7a0609c531 --- /dev/null +++ b/queue-3.4/fuse-readdir-check-for-slash-in-names.patch @@ -0,0 +1,34 @@ +From b5f9e3533584d2fb6c90c63da767b85421b07def Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Tue, 3 Sep 2013 14:28:38 +0200 +Subject: fuse: readdir: check for slash in names + +From: Miklos Szeredi + +commit efeb9e60d48f7778fdcad4a0f3ad9ea9b19e5dfd upstream. + +Userspace can add names containing a slash character to the directory +listing. Don't allow this as it could cause all sorts of trouble. + +Signed-off-by: Miklos Szeredi +[bwh: Backported to 3.2: drop changes to parse_dirplusfile() which we + don't have] +Signed-off-by: Ben Hutchings +Cc: Rui Xiang +Signed-off-by: Greg Kroah-Hartman + +--- + fs/fuse/dir.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/fuse/dir.c ++++ b/fs/fuse/dir.c +@@ -1103,6 +1103,8 @@ static int parse_dirfile(char *buf, size + return -EIO; + if (reclen > nbytes) + break; ++ if (memchr(dirent->name, '/', dirent->namelen) != NULL) ++ return -EIO; + + over = filldir(dstbuf, dirent->name, dirent->namelen, + file->f_pos, dirent->ino, dirent->type); diff --git a/queue-3.4/libceph-unregister-request-in-__map_request-failed-and-nofail-false.patch b/queue-3.4/libceph-unregister-request-in-__map_request-failed-and-nofail-false.patch new file mode 100644 index 00000000000..db8019be7cf --- /dev/null +++ b/queue-3.4/libceph-unregister-request-in-__map_request-failed-and-nofail-false.patch @@ -0,0 +1,35 @@ +From be47dfad8e39e8b849fd0487292b3998284ddbc2 Mon Sep 17 00:00:00 2001 +From: majianpeng +Date: Tue, 16 Jul 2013 15:45:48 +0800 +Subject: libceph: unregister request in __map_request failed and nofail == false + +From: majianpeng + +commit 73d9f7eef3d98c3920e144797cc1894c6b005a1e upstream. + +For nofail == false request, if __map_request failed, the caller does +cleanup work, like releasing the relative pages. It doesn't make any sense +to retry this request. + +Signed-off-by: Jianpeng Ma +Reviewed-by: Sage Weil +[bwh: Backported to 3.2: adjust indentation] +Signed-off-by: Ben Hutchings +Cc: Rui Xiang +Signed-off-by: Greg Kroah-Hartman + +--- + net/ceph/osd_client.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -1721,6 +1721,8 @@ int ceph_osdc_start_request(struct ceph_ + dout("osdc_start_request failed map, " + " will retry %lld\n", req->r_tid); + rc = 0; ++ } else { ++ __unregister_request(osdc, req); + } + goto out_unlock; + } diff --git a/queue-3.4/nilfs2-fix-issue-with-race-condition-of-competition-between-segments-for-dirty-blocks.patch b/queue-3.4/nilfs2-fix-issue-with-race-condition-of-competition-between-segments-for-dirty-blocks.patch new file mode 100644 index 00000000000..f2f26e57e29 --- /dev/null +++ b/queue-3.4/nilfs2-fix-issue-with-race-condition-of-competition-between-segments-for-dirty-blocks.patch @@ -0,0 +1,289 @@ +From ccebcc74c81d8399c7b204aea47c1f33b09c2b17 Mon Sep 17 00:00:00 2001 +From: Vyacheslav Dubeyko +Date: Mon, 30 Sep 2013 13:45:12 -0700 +Subject: nilfs2: fix issue with race condition of competition between segments for dirty blocks + +From: Vyacheslav Dubeyko + +commit 7f42ec3941560f0902fe3671e36f2c20ffd3af0a upstream. + +Many NILFS2 users were reported about strange file system corruption +(for example): + + NILFS: bad btree node (blocknr=185027): level = 0, flags = 0x0, nchildren = 768 + NILFS error (device sda4): nilfs_bmap_last_key: broken bmap (inode number=11540) + +But such error messages are consequence of file system's issue that takes +place more earlier. Fortunately, Jerome Poulin +and Anton Eliasson were reported about another +issue not so recently. These reports describe the issue with segctor +thread's crash: + + BUG: unable to handle kernel paging request at 0000000000004c83 + IP: nilfs_end_page_io+0x12/0xd0 [nilfs2] + + Call Trace: + nilfs_segctor_do_construct+0xf25/0x1b20 [nilfs2] + nilfs_segctor_construct+0x17b/0x290 [nilfs2] + nilfs_segctor_thread+0x122/0x3b0 [nilfs2] + kthread+0xc0/0xd0 + ret_from_fork+0x7c/0xb0 + +These two issues have one reason. This reason can raise third issue +too. Third issue results in hanging of segctor thread with eating of +100% CPU. + +REPRODUCING PATH: + +One of the possible way or the issue reproducing was described by +Jermoe me Poulin : + +1. init S to get to single user mode. +2. sysrq+E to make sure only my shell is running +3. start network-manager to get my wifi connection up +4. login as root and launch "screen" +5. cd /boot/log/nilfs which is a ext3 mount point and can log when NILFS dies. +6. lscp | xz -9e > lscp.txt.xz +7. mount my snapshot using mount -o cp=3360839,ro /dev/vgUbuntu/root /mnt/nilfs +8. start a screen to dump /proc/kmsg to text file since rsyslog is killed +9. start a screen and launch strace -f -o find-cat.log -t find +/mnt/nilfs -type f -exec cat {} > /dev/null \; +10. start a screen and launch strace -f -o apt-get.log -t apt-get update +11. launch the last command again as it did not crash the first time +12. apt-get crashes +13. ps aux > ps-aux-crashed.log +13. sysrq+W +14. sysrq+E wait for everything to terminate +15. sysrq+SUSB + +Simplified way of the issue reproducing is starting kernel compilation +task and "apt-get update" in parallel. + +REPRODUCIBILITY: + +The issue is reproduced not stable [60% - 80%]. It is very important to +have proper environment for the issue reproducing. The critical +conditions for successful reproducing: + +(1) It should have big modified file by mmap() way. + +(2) This file should have the count of dirty blocks are greater that + several segments in size (for example, two or three) from time to time + during processing. + +(3) It should be intensive background activity of files modification + in another thread. + +INVESTIGATION: + +First of all, it is possible to see that the reason of crash is not valid +page address: + + NILFS [nilfs_segctor_complete_write]:2100 bh->b_count 0, bh->b_blocknr 13895680, bh->b_size 13897727, bh->b_page 0000000000001a82 + NILFS [nilfs_segctor_complete_write]:2101 segbuf->sb_segnum 6783 + +Moreover, value of b_page (0x1a82) is 6786. This value looks like segment +number. And b_blocknr with b_size values look like block numbers. So, +buffer_head's pointer points on not proper address value. + +Detailed investigation of the issue is discovered such picture: + + [-----------------------------SEGMENT 6783-------------------------------] + NILFS [nilfs_segctor_do_construct]:2310 nilfs_segctor_begin_construction + NILFS [nilfs_segctor_do_construct]:2321 nilfs_segctor_collect + NILFS [nilfs_segctor_do_construct]:2336 nilfs_segctor_assign + NILFS [nilfs_segctor_do_construct]:2367 nilfs_segctor_update_segusage + NILFS [nilfs_segctor_do_construct]:2371 nilfs_segctor_prepare_write + NILFS [nilfs_segctor_do_construct]:2376 nilfs_add_checksums_on_logs + NILFS [nilfs_segctor_do_construct]:2381 nilfs_segctor_write + NILFS [nilfs_segbuf_submit_bio]:464 bio->bi_sector 111149024, segbuf->sb_segnum 6783 + + [-----------------------------SEGMENT 6784-------------------------------] + NILFS [nilfs_segctor_do_construct]:2310 nilfs_segctor_begin_construction + NILFS [nilfs_segctor_do_construct]:2321 nilfs_segctor_collect + NILFS [nilfs_lookup_dirty_data_buffers]:782 bh->b_count 1, bh->b_page ffffea000709b000, page->index 0, i_ino 1033103, i_size 25165824 + NILFS [nilfs_lookup_dirty_data_buffers]:783 bh->b_assoc_buffers.next ffff8802174a6798, bh->b_assoc_buffers.prev ffff880221cffee8 + NILFS [nilfs_segctor_do_construct]:2336 nilfs_segctor_assign + NILFS [nilfs_segctor_do_construct]:2367 nilfs_segctor_update_segusage + NILFS [nilfs_segctor_do_construct]:2371 nilfs_segctor_prepare_write + NILFS [nilfs_segctor_do_construct]:2376 nilfs_add_checksums_on_logs + NILFS [nilfs_segctor_do_construct]:2381 nilfs_segctor_write + NILFS [nilfs_segbuf_submit_bh]:575 bh->b_count 1, bh->b_page ffffea000709b000, page->index 0, i_ino 1033103, i_size 25165824 + NILFS [nilfs_segbuf_submit_bh]:576 segbuf->sb_segnum 6784 + NILFS [nilfs_segbuf_submit_bh]:577 bh->b_assoc_buffers.next ffff880218a0d5f8, bh->b_assoc_buffers.prev ffff880218bcdf50 + NILFS [nilfs_segbuf_submit_bio]:464 bio->bi_sector 111150080, segbuf->sb_segnum 6784, segbuf->sb_nbio 0 + [----------] ditto + NILFS [nilfs_segbuf_submit_bio]:464 bio->bi_sector 111164416, segbuf->sb_segnum 6784, segbuf->sb_nbio 15 + + [-----------------------------SEGMENT 6785-------------------------------] + NILFS [nilfs_segctor_do_construct]:2310 nilfs_segctor_begin_construction + NILFS [nilfs_segctor_do_construct]:2321 nilfs_segctor_collect + NILFS [nilfs_lookup_dirty_data_buffers]:782 bh->b_count 2, bh->b_page ffffea000709b000, page->index 0, i_ino 1033103, i_size 25165824 + NILFS [nilfs_lookup_dirty_data_buffers]:783 bh->b_assoc_buffers.next ffff880219277e80, bh->b_assoc_buffers.prev ffff880221cffc88 + NILFS [nilfs_segctor_do_construct]:2367 nilfs_segctor_update_segusage + NILFS [nilfs_segctor_do_construct]:2371 nilfs_segctor_prepare_write + NILFS [nilfs_segctor_do_construct]:2376 nilfs_add_checksums_on_logs + NILFS [nilfs_segctor_do_construct]:2381 nilfs_segctor_write + NILFS [nilfs_segbuf_submit_bh]:575 bh->b_count 2, bh->b_page ffffea000709b000, page->index 0, i_ino 1033103, i_size 25165824 + NILFS [nilfs_segbuf_submit_bh]:576 segbuf->sb_segnum 6785 + NILFS [nilfs_segbuf_submit_bh]:577 bh->b_assoc_buffers.next ffff880218a0d5f8, bh->b_assoc_buffers.prev ffff880222cc7ee8 + NILFS [nilfs_segbuf_submit_bio]:464 bio->bi_sector 111165440, segbuf->sb_segnum 6785, segbuf->sb_nbio 0 + [----------] ditto + NILFS [nilfs_segbuf_submit_bio]:464 bio->bi_sector 111177728, segbuf->sb_segnum 6785, segbuf->sb_nbio 12 + + NILFS [nilfs_segctor_do_construct]:2399 nilfs_segctor_wait + NILFS [nilfs_segbuf_wait]:676 segbuf->sb_segnum 6783 + NILFS [nilfs_segbuf_wait]:676 segbuf->sb_segnum 6784 + NILFS [nilfs_segbuf_wait]:676 segbuf->sb_segnum 6785 + + NILFS [nilfs_segctor_complete_write]:2100 bh->b_count 0, bh->b_blocknr 13895680, bh->b_size 13897727, bh->b_page 0000000000001a82 + + BUG: unable to handle kernel paging request at 0000000000001a82 + IP: [] nilfs_end_page_io+0x12/0xd0 [nilfs2] + +Usually, for every segment we collect dirty files in list. Then, dirty +blocks are gathered for every dirty file, prepared for write and +submitted by means of nilfs_segbuf_submit_bh() call. Finally, it takes +place complete write phase after calling nilfs_end_bio_write() on the +block layer. Buffers/pages are marked as not dirty on final phase and +processed files removed from the list of dirty files. + +It is possible to see that we had three prepare_write and submit_bio +phases before segbuf_wait and complete_write phase. Moreover, segments +compete between each other for dirty blocks because on every iteration +of segments processing dirty buffer_heads are added in several lists of +payload_buffers: + + [SEGMENT 6784]: bh->b_assoc_buffers.next ffff880218a0d5f8, bh->b_assoc_buffers.prev ffff880218bcdf50 + [SEGMENT 6785]: bh->b_assoc_buffers.next ffff880218a0d5f8, bh->b_assoc_buffers.prev ffff880222cc7ee8 + +The next pointer is the same but prev pointer has changed. It means +that buffer_head has next pointer from one list but prev pointer from +another. Such modification can be made several times. And, finally, it +can be resulted in various issues: (1) segctor hanging, (2) segctor +crashing, (3) file system metadata corruption. + +FIX: +This patch adds: + +(1) setting of BH_Async_Write flag in nilfs_segctor_prepare_write() + for every proccessed dirty block; + +(2) checking of BH_Async_Write flag in + nilfs_lookup_dirty_data_buffers() and + nilfs_lookup_dirty_node_buffers(); + +(3) clearing of BH_Async_Write flag in nilfs_segctor_complete_write(), + nilfs_abort_logs(), nilfs_forget_buffer(), nilfs_clear_dirty_page(). + +Reported-by: Jerome Poulin +Reported-by: Anton Eliasson +Cc: Paul Fertser +Cc: ARAI Shun-ichi +Cc: Piotr Szymaniak +Cc: Juan Barry Manuel Canham +Cc: Zahid Chowdhury +Cc: Elmer Zhang +Cc: Kenneth Langga +Signed-off-by: Vyacheslav Dubeyko +Acked-by: Ryusuke Konishi +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +[bwh: Backported to 3.2: nilfs_clear_dirty_page() has not been separated + from nilfs_clear_dirty_pages()] +Signed-off-by: Ben Hutchings +Cc: Rui Xiang +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nilfs2/page.c | 2 ++ + fs/nilfs2/segment.c | 11 +++++++++-- + 2 files changed, 11 insertions(+), 2 deletions(-) + +--- a/fs/nilfs2/page.c ++++ b/fs/nilfs2/page.c +@@ -94,6 +94,7 @@ void nilfs_forget_buffer(struct buffer_h + clear_buffer_nilfs_volatile(bh); + clear_buffer_nilfs_checked(bh); + clear_buffer_nilfs_redirected(bh); ++ clear_buffer_async_write(bh); + clear_buffer_dirty(bh); + if (nilfs_page_buffers_clean(page)) + __nilfs_clear_page_dirty(page); +@@ -390,6 +391,7 @@ void nilfs_clear_dirty_pages(struct addr + bh = head = page_buffers(page); + do { + lock_buffer(bh); ++ clear_buffer_async_write(bh); + clear_buffer_dirty(bh); + clear_buffer_nilfs_volatile(bh); + clear_buffer_nilfs_checked(bh); +--- a/fs/nilfs2/segment.c ++++ b/fs/nilfs2/segment.c +@@ -662,7 +662,7 @@ static size_t nilfs_lookup_dirty_data_bu + + bh = head = page_buffers(page); + do { +- if (!buffer_dirty(bh)) ++ if (!buffer_dirty(bh) || buffer_async_write(bh)) + continue; + get_bh(bh); + list_add_tail(&bh->b_assoc_buffers, listp); +@@ -696,7 +696,8 @@ static void nilfs_lookup_dirty_node_buff + for (i = 0; i < pagevec_count(&pvec); i++) { + bh = head = page_buffers(pvec.pages[i]); + do { +- if (buffer_dirty(bh)) { ++ if (buffer_dirty(bh) && ++ !buffer_async_write(bh)) { + get_bh(bh); + list_add_tail(&bh->b_assoc_buffers, + listp); +@@ -1578,6 +1579,7 @@ static void nilfs_segctor_prepare_write( + + list_for_each_entry(bh, &segbuf->sb_segsum_buffers, + b_assoc_buffers) { ++ set_buffer_async_write(bh); + if (bh->b_page != bd_page) { + if (bd_page) { + lock_page(bd_page); +@@ -1591,6 +1593,7 @@ static void nilfs_segctor_prepare_write( + + list_for_each_entry(bh, &segbuf->sb_payload_buffers, + b_assoc_buffers) { ++ set_buffer_async_write(bh); + if (bh == segbuf->sb_super_root) { + if (bh->b_page != bd_page) { + lock_page(bd_page); +@@ -1676,6 +1679,7 @@ static void nilfs_abort_logs(struct list + list_for_each_entry(segbuf, logs, sb_list) { + list_for_each_entry(bh, &segbuf->sb_segsum_buffers, + b_assoc_buffers) { ++ clear_buffer_async_write(bh); + if (bh->b_page != bd_page) { + if (bd_page) + end_page_writeback(bd_page); +@@ -1685,6 +1689,7 @@ static void nilfs_abort_logs(struct list + + list_for_each_entry(bh, &segbuf->sb_payload_buffers, + b_assoc_buffers) { ++ clear_buffer_async_write(bh); + if (bh == segbuf->sb_super_root) { + if (bh->b_page != bd_page) { + end_page_writeback(bd_page); +@@ -1754,6 +1759,7 @@ static void nilfs_segctor_complete_write + b_assoc_buffers) { + set_buffer_uptodate(bh); + clear_buffer_dirty(bh); ++ clear_buffer_async_write(bh); + if (bh->b_page != bd_page) { + if (bd_page) + end_page_writeback(bd_page); +@@ -1775,6 +1781,7 @@ static void nilfs_segctor_complete_write + b_assoc_buffers) { + set_buffer_uptodate(bh); + clear_buffer_dirty(bh); ++ clear_buffer_async_write(bh); + clear_buffer_delay(bh); + clear_buffer_nilfs_volatile(bh); + clear_buffer_nilfs_redirected(bh); diff --git a/queue-3.4/series b/queue-3.4/series index c1875848a45..51dcb439192 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -51,3 +51,7 @@ cgroup-fix-rcu-accesses-to-task-cgroups.patch mm-hotplug-correctly-add-new-zone-to-all-other-nodes-zone-lists.patch perf-tools-remove-extraneous-newline-when-parsing-hardware-cache-events.patch perf-tools-fix-cache-event-name-generation.patch +nilfs2-fix-issue-with-race-condition-of-competition-between-segments-for-dirty-blocks.patch +fuse-readdir-check-for-slash-in-names.patch +fuse-hotfix-truncate_pagecache-issue.patch +libceph-unregister-request-in-__map_request-failed-and-nofail-false.patch