From a6b1d82d079a99d09761ee5fbc66c49f33b42324 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 4 Oct 2006 07:57:18 -0400 Subject: [JFFS2] kill warning RE debug-only variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gcc emits the following warning on a 'allmodconfig' build: fs/jffs2/xattr.c: In function ‘unrefer_xattr_datum’: fs/jffs2/xattr.c:402: warning: unused variable ‘version’ fs/jffs2/xattr.c:402: warning: unused variable ‘xid’ Given that these variables are only used in the debug printk, and they merely remove a deref, we can easily kill the warning by adding the derefs to the debug printk. Signed-off-by: Jeff Garzik Signed-off-by: David Woodhouse --- fs/jffs2/xattr.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index 4da09ce1d1..4bb3f18973 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c @@ -399,8 +399,6 @@ static void unrefer_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datu { /* must be called under down_write(xattr_sem) */ if (atomic_dec_and_lock(&xd->refcnt, &c->erase_completion_lock)) { - uint32_t xid = xd->xid, version = xd->version; - unload_xattr_datum(c, xd); xd->flags |= JFFS2_XFLAGS_DEAD; if (xd->node == (void *)xd) { @@ -411,7 +409,8 @@ static void unrefer_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datu } spin_unlock(&c->erase_completion_lock); - dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n", xid, version); + dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n", + xd->xid, xd->version); } } -- cgit v1.2.2 From ea7415cca922389b4f3c0cf75e0af9fbf827880e Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Fri, 20 Oct 2006 14:41:05 -0700 Subject: [JFFS2] Use rb_first() and rb_last() cleanup Use rb_first() and rb_last() to implement frag_first() and frag_last(). Signed-off-by: Akinbou Mita Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- fs/jffs2/nodelist.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 0ddfd70307..4178b4b559 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -294,23 +294,21 @@ static inline int jffs2_encode_dev(union jffs2_device_node *jdev, dev_t rdev) static inline struct jffs2_node_frag *frag_first(struct rb_root *root) { - struct rb_node *node = root->rb_node; + struct rb_node *node = rb_first(root); if (!node) return NULL; - while(node->rb_left) - node = node->rb_left; + return rb_entry(node, struct jffs2_node_frag, rb); } static inline struct jffs2_node_frag *frag_last(struct rb_root *root) { - struct rb_node *node = root->rb_node; + struct rb_node *node = rb_last(root); if (!node) return NULL; - while(node->rb_right) - node = node->rb_right; + return rb_entry(node, struct jffs2_node_frag, rb); } -- cgit v1.2.2 From c7cf0c68ea4e2020db7204eb0ed4412b2cbb167d Mon Sep 17 00:00:00 2001 From: Qi Yong Date: Mon, 16 Oct 2006 19:42:23 +0800 Subject: [JFFS2] Fix jffs2_follow_link() typo typo fix: noticed this typo while reading the patch "jffs2: fix symlink error handling" Signed-off-by: David Woodhouse --- fs/jffs2/symlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c index fc211b6e9b..b90d5aa3d9 100644 --- a/fs/jffs2/symlink.c +++ b/fs/jffs2/symlink.c @@ -51,7 +51,7 @@ static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) */ if (!p) { - printk(KERN_ERR "jffs2_follow_link(): can't find symlink taerget\n"); + printk(KERN_ERR "jffs2_follow_link(): can't find symlink target\n"); p = ERR_PTR(-EIO); } D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->target)); -- cgit v1.2.2 From 7014568bad55c20b7ee4f439d78c9e875912d51f Mon Sep 17 00:00:00 2001 From: Vitaly Wool Date: Fri, 3 Nov 2006 18:20:38 +0300 Subject: [MTD] [NAND] remove len/ooblen confusion. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As was discussed between Ricard Wanderlöf, David Woodhouse, Artem Bityutskiy and me, the current API for reading/writing OOB is confusing. The thing that introduces confusion is the need to specify ops.len together with ops.ooblen for reads/writes that concern only OOB not data area. So, ops.len is overloaded: when ops.datbuf != NULL it serves to specify the length of the data read, and when ops.datbuf == NULL, it serves to specify the full OOB read length. The patch inlined below is the slightly updated version of the previous patch serving the same purpose, but with the new Artem's comments taken into account. Artem, BTW, thanks a lot for your valuable input! Signed-off-by: Vitaly Wool Signed-off-by: David Woodhouse --- fs/jffs2/wbuf.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'fs') diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index b9b700730d..dcb18e9a64 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -968,8 +968,7 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c, int oobsize = c->mtd->oobsize; struct mtd_oob_ops ops; - ops.len = NR_OOB_SCAN_PAGES * oobsize; - ops.ooblen = oobsize; + ops.ooblen = NR_OOB_SCAN_PAGES * oobsize; ops.oobbuf = c->oobbuf; ops.ooboffs = 0; ops.datbuf = NULL; @@ -982,10 +981,10 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c, return ret; } - if (ops.retlen < ops.len) { + if (ops.oobretlen < ops.ooblen) { D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB " "returned short read (%zd bytes not %d) for block " - "at %08x\n", ops.retlen, ops.len, jeb->offset)); + "at %08x\n", ops.oobretlen, ops.ooblen, jeb->offset)); return -EIO; } @@ -1004,7 +1003,7 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c, } /* we know, we are aligned :) */ - for (page = oobsize; page < ops.len; page += sizeof(long)) { + for (page = oobsize; page < ops.ooblen; page += sizeof(long)) { long dat = *(long *)(&ops.oobbuf[page]); if(dat != -1) return 1; @@ -1032,7 +1031,6 @@ int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c, return 2; } - ops.len = oobsize; ops.ooblen = oobsize; ops.oobbuf = c->oobbuf; ops.ooboffs = 0; @@ -1047,10 +1045,10 @@ int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c, return ret; } - if (ops.retlen < ops.len) { + if (ops.oobretlen < ops.ooblen) { D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): " "Read OOB return short read (%zd bytes not %d) " - "for block at %08x\n", ops.retlen, ops.len, + "for block at %08x\n", ops.oobretlen, ops.ooblen, jeb->offset)); return -EIO; } @@ -1089,8 +1087,7 @@ int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); n.totlen = cpu_to_je32(8); - ops.len = c->fsdata_len; - ops.ooblen = c->fsdata_len;; + ops.ooblen = c->fsdata_len; ops.oobbuf = (uint8_t *)&n; ops.ooboffs = c->fsdata_pos; ops.datbuf = NULL; @@ -1104,10 +1101,10 @@ int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, jeb->offset, ret)); return ret; } - if (ops.retlen != ops.len) { + if (ops.oobretlen != ops.ooblen) { D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): " "Short write for block at %08x: %zd not %d\n", - jeb->offset, ops.retlen, ops.len)); + jeb->offset, ops.oobretlen, ops.ooblen)); return -EIO; } return 0; -- cgit v1.2.2 From 9c74034f8fc5d93fbe5656421cbbdc4c76ddda28 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 11 Oct 2006 14:52:47 +0300 Subject: [MTD] return error code from get_mtd_device() get_mtd_device() returns NULL in case of any failure. Teach it to return an error code instead. Fix all users as well. Signed-off-by: Artem Bityutskiy --- fs/jffs/jffs_fm.c | 3 ++- fs/jffs2/super.c | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/jffs/jffs_fm.c b/fs/jffs/jffs_fm.c index 29b68d939b..6aab317f56 100644 --- a/fs/jffs/jffs_fm.c +++ b/fs/jffs/jffs_fm.c @@ -17,6 +17,7 @@ * */ #include +#include #include #include #include "jffs_fm.h" @@ -104,7 +105,7 @@ jffs_build_begin(struct jffs_control *c, int unit) mtd = get_mtd_device(NULL, unit); - if (!mtd) { + if (IS_ERR(mtd)) { kfree(fmc); DJM(no_jffs_fmcontrol--); return NULL; diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index bc4b8106a4..590f60a897 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -184,9 +185,9 @@ static int jffs2_get_sb_mtdnr(struct file_system_type *fs_type, struct mtd_info *mtd; mtd = get_mtd_device(NULL, mtdnr); - if (!mtd) { + if (IS_ERR(mtd)) { D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr)); - return -EINVAL; + return PTR_ERR(mtd); } return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt); @@ -221,7 +222,7 @@ static int jffs2_get_sb(struct file_system_type *fs_type, D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd:%%s, name \"%s\"\n", dev_name+4)); for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) { mtd = get_mtd_device(NULL, mtdnr); - if (mtd) { + if (!IS_ERR(mtd)) { if (!strcmp(mtd->name, dev_name+4)) return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt); put_mtd_device(mtd); -- cgit v1.2.2 From 3d375d9e0feee79e63a552a3eb3b46f989afce34 Mon Sep 17 00:00:00 2001 From: Yan Burman Date: Mon, 4 Dec 2006 15:03:01 -0800 Subject: [JFFS2] replace kmalloc+memset with kzalloc Replace kmalloc+memset with kzalloc Signed-off-by: Yan Burman Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- fs/jffs2/fs.c | 3 +-- fs/jffs2/readinode.c | 3 +-- fs/jffs2/scan.c | 3 +-- fs/jffs2/summary.c | 4 +--- 4 files changed, 4 insertions(+), 9 deletions(-) (limited to 'fs') diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 7bc1a4201c..abb90c0c09 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -502,12 +502,11 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) if (ret) return ret; - c->inocache_list = kmalloc(INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *), GFP_KERNEL); + c->inocache_list = kcalloc(INOCACHE_HASHSIZE, sizeof(struct jffs2_inode_cache *), GFP_KERNEL); if (!c->inocache_list) { ret = -ENOMEM; goto out_wbuf; } - memset(c->inocache_list, 0, INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *)); jffs2_init_xattr_subsystem(c); diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 266423b270..58a0b912e9 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -944,13 +944,12 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) { struct jffs2_raw_inode n; - struct jffs2_inode_info *f = kmalloc(sizeof(*f), GFP_KERNEL); + struct jffs2_inode_info *f = kzalloc(sizeof(*f), GFP_KERNEL); int ret; if (!f) return -ENOMEM; - memset(f, 0, sizeof(*f)); init_MUTEX_LOCKED(&f->sem); f->inocache = ic; diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index e2413466dd..ee4fc50b0b 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -128,12 +128,11 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) } if (jffs2_sum_active()) { - s = kmalloc(sizeof(struct jffs2_summary), GFP_KERNEL); + s = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL); if (!s) { JFFS2_WARNING("Can't allocate memory for summary\n"); return -ENOMEM; } - memset(s, 0, sizeof(struct jffs2_summary)); } for (i=0; inr_blocks; i++) { diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index e52cef526d..c4f7e4703c 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c @@ -26,15 +26,13 @@ int jffs2_sum_init(struct jffs2_sb_info *c) { - c->summary = kmalloc(sizeof(struct jffs2_summary), GFP_KERNEL); + c->summary = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL); if (!c->summary) { JFFS2_WARNING("Can't allocate memory for summary information!\n"); return -ENOMEM; } - memset(c->summary, 0, sizeof(struct jffs2_summary)); - c->summary->sum_buf = vmalloc(c->sector_size); if (!c->summary->sum_buf) { -- cgit v1.2.2 From aba54da3d05e910199ea8255992c244c9abadd91 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 19 Dec 2006 15:45:23 +0200 Subject: [JFFS2] add cond_resched() when garbage collecting deletion dirent We observe soft lockups when doing heavy test which creates directory with a lot of direntries and deletes them. This cycle is the reason fo this. Make it nicer and add cond_resched() inside of it. Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- fs/jffs2/gc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs') diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index daff3341ff..3a3cf22598 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -838,6 +838,8 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) { + cond_resched(); + /* We only care about obsolete ones */ if (!(ref_obsolete(raw))) continue; -- cgit v1.2.2 From 85de3d9bc779c198f8667cffc291b0ecad082b5e Mon Sep 17 00:00:00 2001 From: Amit Choudhary Date: Tue, 2 Jan 2007 21:16:10 +0000 Subject: [JFFS2] Fix error-path leak in summary scan Signed-off-by: Amit Choudhary Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- fs/jffs2/scan.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index ee4fc50b0b..a167e1c5d0 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -130,6 +130,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) if (jffs2_sum_active()) { s = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL); if (!s) { + kfree(flashbuf); JFFS2_WARNING("Can't allocate memory for summary\n"); return -ENOMEM; } -- cgit v1.2.2 From a2166b933ef9099b4fa6860b165e6dac553a97aa Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Thu, 28 Dec 2006 12:01:41 +0200 Subject: [JFFS2] Reschedule in loops Make JFFS2 nicer and teach it to call cond_resched() in loops which may be quite large. Signed-off-by: Artem Bityutskiy --- fs/jffs2/scan.c | 2 ++ fs/jffs2/summary.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'fs') diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index a167e1c5d0..3af746eaff 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -139,6 +139,8 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) for (i=0; inr_blocks; i++) { struct jffs2_eraseblock *jeb = &c->blocks[i]; + cond_resched(); + /* reset summary info for next eraseblock scan */ jffs2_sum_reset_collected(s); diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index c4f7e4703c..25265965bd 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c @@ -396,6 +396,8 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras for (i=0; isum_num); i++) { dbg_summary("processing summary index %d\n", i); + cond_resched(); + /* Make sure there's a spare ref for dirty space */ err = jffs2_prealloc_raw_node_refs(c, jeb, 2); if (err) -- cgit v1.2.2 From abb536e7ac8719243cfc4b40b39bf3eefd028f82 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Fri, 22 Dec 2006 16:39:30 +0900 Subject: [JFFS2] use the ref_offset macro Don't use ref->flash_offset directly in debugging code, use the ref_offset macro instead. Signed-off-by: Kyungmin Park Signed-off-by: Artem Bityutskiy --- fs/jffs2/debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c index 72b4fc13a1..4189e4a360 100644 --- a/fs/jffs2/debug.c +++ b/fs/jffs2/debug.c @@ -178,8 +178,8 @@ __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c, while (ref2) { uint32_t totlen = ref_totlen(c, jeb, ref2); - if (ref2->flash_offset < jeb->offset || - ref2->flash_offset > jeb->offset + c->sector_size) { + if (ref_offset(ref2) < jeb->offset || + ref_offset(ref2) > jeb->offset + c->sector_size) { JFFS2_ERROR("node_ref %#08x shouldn't be in block at %#08x.\n", ref_offset(ref2), jeb->offset); goto error; -- cgit v1.2.2 From e499e01d234a31d59679b7b1e1cf628d917ba49a Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sat, 13 Jan 2007 08:19:03 +0800 Subject: [JFFS2] debug.h: include for current->pid Signed-off-by: David Woodhouse --- fs/jffs2/debug.h | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 3daf3bca03..f89c85d5a3 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -13,6 +13,7 @@ #ifndef _JFFS2_DEBUG_H_ #define _JFFS2_DEBUG_H_ +#include #ifndef CONFIG_JFFS2_FS_DEBUG #define CONFIG_JFFS2_FS_DEBUG 0 -- cgit v1.2.2 From 790816dd54e22827f63c8cbb30bd623d3d45e594 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 22 Jan 2007 20:40:35 -0800 Subject: [PATCH] blockdev direct_io: fix signedness bug size_t is unsigned. IO errors aren't getting through. Cc: "Chen, Kenneth W" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/block_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/block_dev.c b/fs/block_dev.c index 8b18e43b82..da020be25d 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -146,7 +146,7 @@ static int blk_end_aio(struct bio *bio, unsigned int bytes_done, int error) iocb->ki_nbytes = -EIO; if (atomic_dec_and_test(bio_count)) { - if (iocb->ki_nbytes < 0) + if ((long)iocb->ki_nbytes < 0) aio_complete(iocb, iocb->ki_nbytes, 0); else aio_complete(iocb, iocb->ki_left, 0); -- cgit v1.2.2 From cda9205da24aeaa8fb086b0fb85cdf39571ecc3f Mon Sep 17 00:00:00 2001 From: "Chen, Kenneth W" Date: Mon, 22 Jan 2007 20:40:43 -0800 Subject: [PATCH] fix blk_direct_IO bio preparation For large size DIO that needs multiple bio, one full page worth of data was lost at the boundary of bio's maximum sector or segment limits. After a bio is full and got submitted. The outer while (nbytes) { ... } loop will allocate a new bio and just march on to index into next page. It just forgets about the page that bio_add_page() rejected when previous bio is full. Fix it by put the rejected page back to pvec so we pick it up again for the next bio. Signed-off-by: Ken Chen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/block_dev.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'fs') diff --git a/fs/block_dev.c b/fs/block_dev.c index da020be25d..d9bdf2b3ad 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -190,6 +190,12 @@ static struct page *blk_get_page(unsigned long addr, size_t count, int rw, return pvec->page[pvec->idx++]; } +/* return a page back to pvec array */ +static void blk_unget_page(struct page *page, struct pvec *pvec) +{ + pvec->page[--pvec->idx] = page; +} + static ssize_t blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs) @@ -278,6 +284,8 @@ same_bio: count = min(count, nbytes); goto same_bio; } + } else { + blk_unget_page(page, &pvec); } /* bio is ready, submit it */ -- cgit v1.2.2 From de14569f94513279e3d44d9571a421e9da1759ae Mon Sep 17 00:00:00 2001 From: Vladimir Saveliev Date: Mon, 22 Jan 2007 20:40:46 -0800 Subject: [PATCH] resierfs: avoid tail packing if an inode was ever mmapped This patch fixes a confusion reiserfs has for a long time. On release file operation reiserfs used to try to pack file data stored in last incomplete page of some files into metadata blocks. After packing the page got cleared with clear_page_dirty. It did not take into account that the page may be mmaped into other process's address space. Recent replacement for clear_page_dirty cancel_dirty_page found the confusion with sanity check that page has to be not mapped. The patch fixes the confusion by making reiserfs avoid tail packing if an inode was ever mmapped. reiserfs_mmap and reiserfs_file_release are serialized with mutex in reiserfs specific inode. reiserfs_mmap locks the mutex and sets a bit in reiserfs specific inode flags. reiserfs_file_release checks the bit having the mutex locked. If bit is set - tail packing is avoided. This eliminates a possibility that mmapped page gets cancel_page_dirty-ed. Signed-off-by: Vladimir Saveliev Cc: Jeff Mahoney Cc: Chris Mason Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/file.c | 20 +++++++++++++++++++- fs/reiserfs/inode.c | 2 ++ 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index 99b6f329ba..5109f1d5e7 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c @@ -48,6 +48,11 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp) } mutex_lock(&inode->i_mutex); + + mutex_lock(&(REISERFS_I(inode)->i_mmap)); + if (REISERFS_I(inode)->i_flags & i_ever_mapped) + REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask; + reiserfs_write_lock(inode->i_sb); /* freeing preallocation only involves relogging blocks that * are already in the current transaction. preallocation gets @@ -100,11 +105,24 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp) err = reiserfs_truncate_file(inode, 0); } out: + mutex_unlock(&(REISERFS_I(inode)->i_mmap)); mutex_unlock(&inode->i_mutex); reiserfs_write_unlock(inode->i_sb); return err; } +static int reiserfs_file_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct inode *inode; + + inode = file->f_path.dentry->d_inode; + mutex_lock(&(REISERFS_I(inode)->i_mmap)); + REISERFS_I(inode)->i_flags |= i_ever_mapped; + mutex_unlock(&(REISERFS_I(inode)->i_mmap)); + + return generic_file_mmap(file, vma); +} + static void reiserfs_vfs_truncate_file(struct inode *inode) { reiserfs_truncate_file(inode, 1); @@ -1527,7 +1545,7 @@ const struct file_operations reiserfs_file_operations = { #ifdef CONFIG_COMPAT .compat_ioctl = reiserfs_compat_ioctl, #endif - .mmap = generic_file_mmap, + .mmap = reiserfs_file_mmap, .open = generic_file_open, .release = reiserfs_file_release, .fsync = reiserfs_sync_file, diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index f3d1c4a779..9fcbfe3169 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1125,6 +1125,7 @@ static void init_inode(struct inode *inode, struct treepath *path) REISERFS_I(inode)->i_prealloc_count = 0; REISERFS_I(inode)->i_trans_id = 0; REISERFS_I(inode)->i_jl = NULL; + mutex_init(&(REISERFS_I(inode)->i_mmap)); reiserfs_init_acl_access(inode); reiserfs_init_acl_default(inode); reiserfs_init_xattr_rwsem(inode); @@ -1832,6 +1833,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, REISERFS_I(inode)->i_attrs = REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK; sd_attrs_to_i_attrs(REISERFS_I(inode)->i_attrs, inode); + mutex_init(&(REISERFS_I(inode)->i_mmap)); reiserfs_init_acl_access(inode); reiserfs_init_acl_default(inode); reiserfs_init_xattr_rwsem(inode); -- cgit v1.2.2