Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 142617
b: refs/heads/master
c: 9ff0512
h: refs/heads/master
i:
  142615: 11eb228
v: v3
  • Loading branch information
Ryusuke Konishi authored and Linus Torvalds committed Apr 7, 2009
1 parent 823eb0b commit f859824
Show file tree
Hide file tree
Showing 5 changed files with 3,578 additions and 4 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: 64b5a32e0b3680a9655b3f2e668a646068e71d33
refs/heads/master: 9ff05123e3bfbb1d2b68ba1d9bf1f7d1dffc1453
62 changes: 59 additions & 3 deletions trunk/fs/nilfs2/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,66 @@ nilfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
return ret;
}

static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct page *page)
static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
{
if (!(vma->vm_flags & (VM_WRITE | VM_MAYWRITE)))
return -EPERM;
struct page *page = vmf->page;
struct inode *inode = vma->vm_file->f_dentry->d_inode;
struct nilfs_transaction_info ti;
int ret;

if (unlikely(nilfs_near_disk_full(NILFS_SB(inode->i_sb)->s_nilfs)))
return VM_FAULT_SIGBUS; /* -ENOSPC */

lock_page(page);
if (page->mapping != inode->i_mapping ||
page_offset(page) >= i_size_read(inode) || !PageUptodate(page)) {
unlock_page(page);
return VM_FAULT_NOPAGE; /* make the VM retry the fault */
}

/*
* check to see if the page is mapped already (no holes)
*/
if (PageMappedToDisk(page)) {
unlock_page(page);
goto mapped;
}
if (page_has_buffers(page)) {
struct buffer_head *bh, *head;
int fully_mapped = 1;

bh = head = page_buffers(page);
do {
if (!buffer_mapped(bh)) {
fully_mapped = 0;
break;
}
} while (bh = bh->b_this_page, bh != head);

if (fully_mapped) {
SetPageMappedToDisk(page);
unlock_page(page);
goto mapped;
}
}
unlock_page(page);

/*
* fill hole blocks
*/
ret = nilfs_transaction_begin(inode->i_sb, &ti, 1);
/* never returns -ENOMEM, but may return -ENOSPC */
if (unlikely(ret))
return VM_FAULT_SIGBUS;

ret = block_page_mkwrite(vma, vmf, nilfs_get_block);
if (unlikely(ret)) {
nilfs_transaction_abort(inode->i_sb);
return ret;
}
nilfs_transaction_commit(inode->i_sb);

mapped:
SetPageChecked(page);
wait_on_page_writeback(page);
return 0;
Expand Down
85 changes: 85 additions & 0 deletions trunk/fs/nilfs2/seglist.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* seglist.h - expediential structure and routines to handle list of segments
* (would be removed in a future release)
*
* Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Written by Ryusuke Konishi <ryusuke@osrg.net>
*
*/
#ifndef _NILFS_SEGLIST_H
#define _NILFS_SEGLIST_H

#include <linux/fs.h>
#include <linux/buffer_head.h>
#include <linux/nilfs2_fs.h>
#include "sufile.h"

struct nilfs_segment_entry {
__u64 segnum;

#define NILFS_SLH_FREED 0x0001 /* The segment was freed provisonally.
It must be cancelled if
construction aborted */

unsigned flags;
struct list_head list;
struct buffer_head *bh_su;
struct nilfs_segment_usage *raw_su;
};


void nilfs_dispose_segment_list(struct list_head *);

static inline struct nilfs_segment_entry *
nilfs_alloc_segment_entry(__u64 segnum)
{
struct nilfs_segment_entry *ent = kmalloc(sizeof(*ent), GFP_NOFS);

if (likely(ent)) {
ent->segnum = segnum;
ent->flags = 0;
ent->bh_su = NULL;
ent->raw_su = NULL;
INIT_LIST_HEAD(&ent->list);
}
return ent;
}

static inline int nilfs_open_segment_entry(struct nilfs_segment_entry *ent,
struct inode *sufile)
{
return nilfs_sufile_get_segment_usage(sufile, ent->segnum,
&ent->raw_su, &ent->bh_su);
}

static inline void nilfs_close_segment_entry(struct nilfs_segment_entry *ent,
struct inode *sufile)
{
if (!ent->bh_su)
return;
nilfs_sufile_put_segment_usage(sufile, ent->segnum, ent->bh_su);
ent->bh_su = NULL;
ent->raw_su = NULL;
}

static inline void nilfs_free_segment_entry(struct nilfs_segment_entry *ent)
{
kfree(ent);
}

#endif /* _NILFS_SEGLIST_H */
Loading

0 comments on commit f859824

Please sign in to comment.