Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 101104
b: refs/heads/master
c: 2e9ee85
h: refs/heads/master
v: v3
  • Loading branch information
Aneesh Kumar K.V authored and Theodore Ts'o committed Jul 11, 2008
1 parent 2f678b5 commit d42ea67
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 93e3270c87549dc531a0b0e5d06362d998d810cb
refs/heads/master: 2e9ee850355593e311d9a26542290fe51e152f74
1 change: 1 addition & 0 deletions trunk/fs/ext4/ext4.h
Original file line number Diff line number Diff line change
Expand Up @@ -1068,6 +1068,7 @@ extern void ext4_set_aops(struct inode *inode);
extern int ext4_writepage_trans_blocks(struct inode *);
extern int ext4_block_truncate_page(handle_t *handle, struct page *page,
struct address_space *mapping, loff_t from);
extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page);

/* ioctl.c */
extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
Expand Down
19 changes: 18 additions & 1 deletion trunk/fs/ext4/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,23 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
return ret;
}

static struct vm_operations_struct ext4_file_vm_ops = {
.fault = filemap_fault,
.page_mkwrite = ext4_page_mkwrite,
};

static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma)
{
struct address_space *mapping = file->f_mapping;

if (!mapping->a_ops->readpage)
return -ENOEXEC;
file_accessed(file);
vma->vm_ops = &ext4_file_vm_ops;
vma->vm_flags |= VM_CAN_NONLINEAR;
return 0;
}

const struct file_operations ext4_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
Expand All @@ -133,7 +150,7 @@ const struct file_operations ext4_file_operations = {
#ifdef CONFIG_COMPAT
.compat_ioctl = ext4_compat_ioctl,
#endif
.mmap = generic_file_mmap,
.mmap = ext4_file_mmap,
.open = generic_file_open,
.release = ext4_release_file,
.fsync = ext4_sync_file,
Expand Down
61 changes: 61 additions & 0 deletions trunk/fs/ext4/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -3564,3 +3564,64 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)

return err;
}

static int ext4_bh_unmapped(handle_t *handle, struct buffer_head *bh)
{
return !buffer_mapped(bh);
}

int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page)
{
loff_t size;
unsigned long len;
int ret = -EINVAL;
struct file *file = vma->vm_file;
struct inode *inode = file->f_path.dentry->d_inode;
struct address_space *mapping = inode->i_mapping;

/*
* Get i_alloc_sem to stop truncates messing with the inode. We cannot
* get i_mutex because we are already holding mmap_sem.
*/
down_read(&inode->i_alloc_sem);
size = i_size_read(inode);
if (page->mapping != mapping || size <= page_offset(page)
|| !PageUptodate(page)) {
/* page got truncated from under us? */
goto out_unlock;
}
ret = 0;
if (PageMappedToDisk(page))
goto out_unlock;

if (page->index == size >> PAGE_CACHE_SHIFT)
len = size & ~PAGE_CACHE_MASK;
else
len = PAGE_CACHE_SIZE;

if (page_has_buffers(page)) {
/* return if we have all the buffers mapped */
if (!walk_page_buffers(NULL, page_buffers(page), 0, len, NULL,
ext4_bh_unmapped))
goto out_unlock;
}
/*
* OK, we need to fill the hole... Do write_begin write_end
* to do block allocation/reservation.We are not holding
* inode.i__mutex here. That allow * parallel write_begin,
* write_end call. lock_page prevent this from happening
* on the same page though
*/
ret = mapping->a_ops->write_begin(file, mapping, page_offset(page),
len, AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
if (ret < 0)
goto out_unlock;
ret = mapping->a_ops->write_end(file, mapping, page_offset(page),
len, len, page, NULL);
if (ret < 0)
goto out_unlock;
ret = 0;
out_unlock:
up_read(&inode->i_alloc_sem);
return ret;
}

0 comments on commit d42ea67

Please sign in to comment.