diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-12-30 13:59:37 -0200 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-12-30 13:59:37 -0200 |
commit | b4d48c942c17ce3d3a330ad91e109e522bc97378 (patch) | |
tree | 3365292f3a5a502edb51492d011fd326c930ca40 /fs/ocfs2/mmap.c | |
parent | 1a5cd29631a6b75e49e6ad8a770ab9d69cda0fa2 (diff) | |
parent | 5f0a6e2d503896062f641639dacfe5055c2f593b (diff) | |
download | talos-op-linux-b4d48c942c17ce3d3a330ad91e109e522bc97378.tar.gz talos-op-linux-b4d48c942c17ce3d3a330ad91e109e522bc97378.zip |
Merge tag 'v3.2-rc7' into staging/for_v3.3
Linux 3.2-rc7
* tag 'v3.2-rc7': (1304 commits)
Linux 3.2-rc7
netfilter: xt_connbytes: handle negation correctly
Btrfs: call d_instantiate after all ops are setup
Btrfs: fix worker lock misuse in find_worker
net: relax rcvbuf limits
rps: fix insufficient bounds checking in store_rps_dev_flow_table_cnt()
net: introduce DST_NOPEER dst flag
mqprio: Avoid panic if no options are provided
bridge: provide a mtu() method for fake_dst_ops
md/bitmap: It is OK to clear bits during recovery.
md: don't give up looking for spares on first failure-to-add
md/raid5: ensure correct assessment of drives during degraded reshape.
md/linear: fix hot-add of devices to linear arrays.
sparc64: Fix MSIQ HV call ordering in pci_sun4v_msiq_build_irq().
pata_of_platform: Add missing CONFIG_OF_IRQ dependency.
ipv4: using prefetch requires including prefetch.h
VFS: Fix race between CPU hotplug and lglocks
vfs: __read_cache_page should use gfp argument rather than GFP_KERNEL
USB: Fix usb/isp1760 build on sparc
net: Add a flow_cache_flush_deferred function
...
Conflicts:
drivers/media/common/tuners/tda18218.c
drivers/media/video/omap3isp/ispccdc.c
drivers/staging/media/as102/as102_drv.h
Diffstat (limited to 'fs/ocfs2/mmap.c')
-rw-r--r-- | fs/ocfs2/mmap.c | 53 |
1 files changed, 24 insertions, 29 deletions
diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c index 3e9393ca39eb..9cd41083e991 100644 --- a/fs/ocfs2/mmap.c +++ b/fs/ocfs2/mmap.c @@ -61,7 +61,7 @@ static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf) static int __ocfs2_page_mkwrite(struct file *file, struct buffer_head *di_bh, struct page *page) { - int ret; + int ret = VM_FAULT_NOPAGE; struct inode *inode = file->f_path.dentry->d_inode; struct address_space *mapping = inode->i_mapping; loff_t pos = page_offset(page); @@ -71,32 +71,25 @@ static int __ocfs2_page_mkwrite(struct file *file, struct buffer_head *di_bh, void *fsdata; loff_t size = i_size_read(inode); - /* - * Another node might have truncated while we were waiting on - * cluster locks. - * We don't check size == 0 before the shift. This is borrowed - * from do_generic_file_read. - */ last_index = (size - 1) >> PAGE_CACHE_SHIFT; - if (unlikely(!size || page->index > last_index)) { - ret = -EINVAL; - goto out; - } /* - * The i_size check above doesn't catch the case where nodes - * truncated and then re-extended the file. We'll re-check the - * page mapping after taking the page lock inside of - * ocfs2_write_begin_nolock(). + * There are cases that lead to the page no longer bebongs to the + * mapping. + * 1) pagecache truncates locally due to memory pressure. + * 2) pagecache truncates when another is taking EX lock against + * inode lock. see ocfs2_data_convert_worker. + * + * The i_size check doesn't catch the case where nodes truncated and + * then re-extended the file. We'll re-check the page mapping after + * taking the page lock inside of ocfs2_write_begin_nolock(). + * + * Let VM retry with these cases. */ - if (!PageUptodate(page) || page->mapping != inode->i_mapping) { - /* - * the page has been umapped in ocfs2_data_downconvert_worker. - * So return 0 here and let VFS retry. - */ - ret = 0; + if ((page->mapping != inode->i_mapping) || + (!PageUptodate(page)) || + (page_offset(page) >= size)) goto out; - } /* * Call ocfs2_write_begin() and ocfs2_write_end() to take @@ -116,17 +109,21 @@ static int __ocfs2_page_mkwrite(struct file *file, struct buffer_head *di_bh, if (ret) { if (ret != -ENOSPC) mlog_errno(ret); + if (ret == -ENOMEM) + ret = VM_FAULT_OOM; + else + ret = VM_FAULT_SIGBUS; goto out; } - ret = ocfs2_write_end_nolock(mapping, pos, len, len, locked_page, - fsdata); - if (ret < 0) { - mlog_errno(ret); + if (!locked_page) { + ret = VM_FAULT_NOPAGE; goto out; } + ret = ocfs2_write_end_nolock(mapping, pos, len, len, locked_page, + fsdata); BUG_ON(ret != len); - ret = 0; + ret = VM_FAULT_LOCKED; out: return ret; } @@ -168,8 +165,6 @@ static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) out: ocfs2_unblock_signals(&oldset); - if (ret) - ret = VM_FAULT_SIGBUS; return ret; } |