From fbfa2cc58d5363f780f4f2ad0243a47185c2bb2a Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Fri, 2 Nov 2012 17:09:44 +0900 Subject: f2fs: add file operations This adds memory operations and file/file_inode operations. - F2FS supports fallocate(), mmap(), fsync(), and basic ioctl(). Signed-off-by: Jaegeuk Kim --- fs/f2fs/file.c | 637 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 637 insertions(+) create mode 100644 fs/f2fs/file.c (limited to 'fs/f2fs/file.c') diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c new file mode 100644 index 000000000000..f5ae36d19f4f --- /dev/null +++ b/fs/f2fs/file.c @@ -0,0 +1,637 @@ +/** + * fs/f2fs/file.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "f2fs.h" +#include "node.h" +#include "segment.h" +#include "xattr.h" +#include "acl.h" + +static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma, + struct vm_fault *vmf) +{ + struct page *page = vmf->page; + struct inode *inode = vma->vm_file->f_path.dentry->d_inode; + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + struct page *node_page; + block_t old_blk_addr; + struct dnode_of_data dn; + int err; + + f2fs_balance_fs(sbi); + + sb_start_pagefault(inode->i_sb); + + mutex_lock_op(sbi, DATA_NEW); + + /* block allocation */ + set_new_dnode(&dn, inode, NULL, NULL, 0); + err = get_dnode_of_data(&dn, page->index, 0); + if (err) { + mutex_unlock_op(sbi, DATA_NEW); + goto out; + } + + old_blk_addr = dn.data_blkaddr; + node_page = dn.node_page; + + if (old_blk_addr == NULL_ADDR) { + err = reserve_new_block(&dn); + if (err) { + f2fs_put_dnode(&dn); + mutex_unlock_op(sbi, DATA_NEW); + goto out; + } + } + f2fs_put_dnode(&dn); + + mutex_unlock_op(sbi, DATA_NEW); + + lock_page(page); + if (page->mapping != inode->i_mapping || + page_offset(page) >= i_size_read(inode) || + !PageUptodate(page)) { + unlock_page(page); + err = -EFAULT; + goto out; + } + + /* + * check to see if the page is mapped already (no holes) + */ + if (PageMappedToDisk(page)) + goto out; + + /* fill the page */ + wait_on_page_writeback(page); + + /* page is wholly or partially inside EOF */ + if (((page->index + 1) << PAGE_CACHE_SHIFT) > i_size_read(inode)) { + unsigned offset; + offset = i_size_read(inode) & ~PAGE_CACHE_MASK; + zero_user_segment(page, offset, PAGE_CACHE_SIZE); + } + set_page_dirty(page); + SetPageUptodate(page); + + file_update_time(vma->vm_file); +out: + sb_end_pagefault(inode->i_sb); + return block_page_mkwrite_return(err); +} + +static const struct vm_operations_struct f2fs_file_vm_ops = { + .fault = filemap_fault, + .page_mkwrite = f2fs_vm_page_mkwrite, +}; + +static int need_to_sync_dir(struct f2fs_sb_info *sbi, struct inode *inode) +{ + struct dentry *dentry; + nid_t pino; + + inode = igrab(inode); + dentry = d_find_any_alias(inode); + if (!dentry) { + iput(inode); + return 0; + } + pino = dentry->d_parent->d_inode->i_ino; + dput(dentry); + iput(inode); + return !is_checkpointed_node(sbi, pino); +} + +int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) +{ + struct inode *inode = file->f_mapping->host; + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + unsigned long long cur_version; + int ret = 0; + bool need_cp = false; + struct writeback_control wbc = { + .sync_mode = WB_SYNC_ALL, + .nr_to_write = LONG_MAX, + .for_reclaim = 0, + }; + + ret = filemap_write_and_wait_range(inode->i_mapping, start, end); + if (ret) + return ret; + + mutex_lock(&inode->i_mutex); + + if (inode->i_sb->s_flags & MS_RDONLY) + goto out; + if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) + goto out; + + mutex_lock(&sbi->cp_mutex); + cur_version = le64_to_cpu(F2FS_CKPT(sbi)->checkpoint_ver); + mutex_unlock(&sbi->cp_mutex); + + if (F2FS_I(inode)->data_version != cur_version && + !(inode->i_state & I_DIRTY)) + goto out; + F2FS_I(inode)->data_version--; + + if (!S_ISREG(inode->i_mode) || inode->i_nlink != 1) + need_cp = true; + if (is_inode_flag_set(F2FS_I(inode), FI_NEED_CP)) + need_cp = true; + if (!space_for_roll_forward(sbi)) + need_cp = true; + if (need_to_sync_dir(sbi, inode)) + need_cp = true; + + f2fs_write_inode(inode, NULL); + + if (need_cp) { + /* all the dirty node pages should be flushed for POR */ + ret = f2fs_sync_fs(inode->i_sb, 1); + clear_inode_flag(F2FS_I(inode), FI_NEED_CP); + } else { + while (sync_node_pages(sbi, inode->i_ino, &wbc) == 0) + f2fs_write_inode(inode, NULL); + filemap_fdatawait_range(sbi->node_inode->i_mapping, + 0, LONG_MAX); + } +out: + mutex_unlock(&inode->i_mutex); + return ret; +} + +static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma) +{ + file_accessed(file); + vma->vm_ops = &f2fs_file_vm_ops; + return 0; +} + +static int truncate_data_blocks_range(struct dnode_of_data *dn, int count) +{ + int nr_free = 0, ofs = dn->ofs_in_node; + struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); + struct f2fs_node *raw_node; + __le32 *addr; + + raw_node = page_address(dn->node_page); + addr = blkaddr_in_node(raw_node) + ofs; + + for ( ; count > 0; count--, addr++, dn->ofs_in_node++) { + block_t blkaddr = le32_to_cpu(*addr); + if (blkaddr == NULL_ADDR) + continue; + + update_extent_cache(NULL_ADDR, dn); + invalidate_blocks(sbi, blkaddr); + dec_valid_block_count(sbi, dn->inode, 1); + nr_free++; + } + if (nr_free) { + set_page_dirty(dn->node_page); + sync_inode_page(dn); + } + dn->ofs_in_node = ofs; + return nr_free; +} + +void truncate_data_blocks(struct dnode_of_data *dn) +{ + truncate_data_blocks_range(dn, ADDRS_PER_BLOCK); +} + +static void truncate_partial_data_page(struct inode *inode, u64 from) +{ + unsigned offset = from & (PAGE_CACHE_SIZE - 1); + struct page *page; + + if (!offset) + return; + + page = find_data_page(inode, from >> PAGE_CACHE_SHIFT); + if (IS_ERR(page)) + return; + + lock_page(page); + wait_on_page_writeback(page); + zero_user(page, offset, PAGE_CACHE_SIZE - offset); + set_page_dirty(page); + f2fs_put_page(page, 1); +} + +static int truncate_blocks(struct inode *inode, u64 from) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + unsigned int blocksize = inode->i_sb->s_blocksize; + struct dnode_of_data dn; + pgoff_t free_from; + int count = 0; + int err; + + free_from = (pgoff_t) + ((from + blocksize - 1) >> (sbi->log_blocksize)); + + mutex_lock_op(sbi, DATA_TRUNC); + + set_new_dnode(&dn, inode, NULL, NULL, 0); + err = get_dnode_of_data(&dn, free_from, RDONLY_NODE); + if (err) { + if (err == -ENOENT) + goto free_next; + mutex_unlock_op(sbi, DATA_TRUNC); + return err; + } + + if (IS_INODE(dn.node_page)) + count = ADDRS_PER_INODE; + else + count = ADDRS_PER_BLOCK; + + count -= dn.ofs_in_node; + BUG_ON(count < 0); + if (dn.ofs_in_node || IS_INODE(dn.node_page)) { + truncate_data_blocks_range(&dn, count); + free_from += count; + } + + f2fs_put_dnode(&dn); +free_next: + err = truncate_inode_blocks(inode, free_from); + mutex_unlock_op(sbi, DATA_TRUNC); + + /* lastly zero out the first data page */ + truncate_partial_data_page(inode, from); + + return err; +} + +void f2fs_truncate(struct inode *inode) +{ + if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || + S_ISLNK(inode->i_mode))) + return; + + if (!truncate_blocks(inode, i_size_read(inode))) { + inode->i_mtime = inode->i_ctime = CURRENT_TIME; + mark_inode_dirty(inode); + } + + f2fs_balance_fs(F2FS_SB(inode->i_sb)); +} + +static int f2fs_getattr(struct vfsmount *mnt, + struct dentry *dentry, struct kstat *stat) +{ + struct inode *inode = dentry->d_inode; + generic_fillattr(inode, stat); + stat->blocks <<= 3; + return 0; +} + +#ifdef CONFIG_F2FS_FS_POSIX_ACL +static void __setattr_copy(struct inode *inode, const struct iattr *attr) +{ + struct f2fs_inode_info *fi = F2FS_I(inode); + unsigned int ia_valid = attr->ia_valid; + + if (ia_valid & ATTR_UID) + inode->i_uid = attr->ia_uid; + if (ia_valid & ATTR_GID) + inode->i_gid = attr->ia_gid; + if (ia_valid & ATTR_ATIME) + inode->i_atime = timespec_trunc(attr->ia_atime, + inode->i_sb->s_time_gran); + if (ia_valid & ATTR_MTIME) + inode->i_mtime = timespec_trunc(attr->ia_mtime, + inode->i_sb->s_time_gran); + if (ia_valid & ATTR_CTIME) + inode->i_ctime = timespec_trunc(attr->ia_ctime, + inode->i_sb->s_time_gran); + if (ia_valid & ATTR_MODE) { + umode_t mode = attr->ia_mode; + + if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) + mode &= ~S_ISGID; + set_acl_inode(fi, mode); + } +} +#else +#define __setattr_copy setattr_copy +#endif + +int f2fs_setattr(struct dentry *dentry, struct iattr *attr) +{ + struct inode *inode = dentry->d_inode; + struct f2fs_inode_info *fi = F2FS_I(inode); + int err; + + err = inode_change_ok(inode, attr); + if (err) + return err; + + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + truncate_setsize(inode, attr->ia_size); + f2fs_truncate(inode); + } + + __setattr_copy(inode, attr); + + if (attr->ia_valid & ATTR_MODE) { + err = f2fs_acl_chmod(inode); + if (err || is_inode_flag_set(fi, FI_ACL_MODE)) { + inode->i_mode = fi->i_acl_mode; + clear_inode_flag(fi, FI_ACL_MODE); + } + } + + mark_inode_dirty(inode); + return err; +} + +const struct inode_operations f2fs_file_inode_operations = { + .getattr = f2fs_getattr, + .setattr = f2fs_setattr, + .get_acl = f2fs_get_acl, +#ifdef CONFIG_F2FS_FS_XATTR + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, + .listxattr = f2fs_listxattr, + .removexattr = generic_removexattr, +#endif +}; + +static void fill_zero(struct inode *inode, pgoff_t index, + loff_t start, loff_t len) +{ + struct page *page; + + if (!len) + return; + + page = get_new_data_page(inode, index, false); + + if (!IS_ERR(page)) { + wait_on_page_writeback(page); + zero_user(page, start, len); + set_page_dirty(page); + f2fs_put_page(page, 1); + } +} + +int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end) +{ + pgoff_t index; + int err; + + for (index = pg_start; index < pg_end; index++) { + struct dnode_of_data dn; + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + + mutex_lock_op(sbi, DATA_TRUNC); + set_new_dnode(&dn, inode, NULL, NULL, 0); + err = get_dnode_of_data(&dn, index, RDONLY_NODE); + if (err) { + mutex_unlock_op(sbi, DATA_TRUNC); + if (err == -ENOENT) + continue; + return err; + } + + if (dn.data_blkaddr != NULL_ADDR) + truncate_data_blocks_range(&dn, 1); + f2fs_put_dnode(&dn); + mutex_unlock_op(sbi, DATA_TRUNC); + } + return 0; +} + +static int punch_hole(struct inode *inode, loff_t offset, loff_t len, int mode) +{ + pgoff_t pg_start, pg_end; + loff_t off_start, off_end; + int ret = 0; + + pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT; + pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT; + + off_start = offset & (PAGE_CACHE_SIZE - 1); + off_end = (offset + len) & (PAGE_CACHE_SIZE - 1); + + if (pg_start == pg_end) { + fill_zero(inode, pg_start, off_start, + off_end - off_start); + } else { + if (off_start) + fill_zero(inode, pg_start++, off_start, + PAGE_CACHE_SIZE - off_start); + if (off_end) + fill_zero(inode, pg_end, 0, off_end); + + if (pg_start < pg_end) { + struct address_space *mapping = inode->i_mapping; + loff_t blk_start, blk_end; + + blk_start = pg_start << PAGE_CACHE_SHIFT; + blk_end = pg_end << PAGE_CACHE_SHIFT; + truncate_inode_pages_range(mapping, blk_start, + blk_end - 1); + ret = truncate_hole(inode, pg_start, pg_end); + } + } + + if (!(mode & FALLOC_FL_KEEP_SIZE) && + i_size_read(inode) <= (offset + len)) { + i_size_write(inode, offset); + mark_inode_dirty(inode); + } + + return ret; +} + +static int expand_inode_data(struct inode *inode, loff_t offset, + loff_t len, int mode) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + pgoff_t index, pg_start, pg_end; + loff_t new_size = i_size_read(inode); + loff_t off_start, off_end; + int ret = 0; + + ret = inode_newsize_ok(inode, (len + offset)); + if (ret) + return ret; + + pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT; + pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT; + + off_start = offset & (PAGE_CACHE_SIZE - 1); + off_end = (offset + len) & (PAGE_CACHE_SIZE - 1); + + for (index = pg_start; index <= pg_end; index++) { + struct dnode_of_data dn; + + mutex_lock_op(sbi, DATA_NEW); + + set_new_dnode(&dn, inode, NULL, NULL, 0); + ret = get_dnode_of_data(&dn, index, 0); + if (ret) { + mutex_unlock_op(sbi, DATA_NEW); + break; + } + + if (dn.data_blkaddr == NULL_ADDR) { + ret = reserve_new_block(&dn); + if (ret) { + f2fs_put_dnode(&dn); + mutex_unlock_op(sbi, DATA_NEW); + break; + } + } + f2fs_put_dnode(&dn); + + mutex_unlock_op(sbi, DATA_NEW); + + if (pg_start == pg_end) + new_size = offset + len; + else if (index == pg_start && off_start) + new_size = (index + 1) << PAGE_CACHE_SHIFT; + else if (index == pg_end) + new_size = (index << PAGE_CACHE_SHIFT) + off_end; + else + new_size += PAGE_CACHE_SIZE; + } + + if (!(mode & FALLOC_FL_KEEP_SIZE) && + i_size_read(inode) < new_size) { + i_size_write(inode, new_size); + mark_inode_dirty(inode); + } + + return ret; +} + +static long f2fs_fallocate(struct file *file, int mode, + loff_t offset, loff_t len) +{ + struct inode *inode = file->f_path.dentry->d_inode; + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + long ret; + + if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) + return -EOPNOTSUPP; + + if (mode & FALLOC_FL_PUNCH_HOLE) + ret = punch_hole(inode, offset, len, mode); + else + ret = expand_inode_data(inode, offset, len, mode); + + f2fs_balance_fs(sbi); + return ret; +} + +#define F2FS_REG_FLMASK (~(FS_DIRSYNC_FL | FS_TOPDIR_FL)) +#define F2FS_OTHER_FLMASK (FS_NODUMP_FL | FS_NOATIME_FL) + +static inline __u32 f2fs_mask_flags(umode_t mode, __u32 flags) +{ + if (S_ISDIR(mode)) + return flags; + else if (S_ISREG(mode)) + return flags & F2FS_REG_FLMASK; + else + return flags & F2FS_OTHER_FLMASK; +} + +long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct inode *inode = filp->f_dentry->d_inode; + struct f2fs_inode_info *fi = F2FS_I(inode); + unsigned int flags; + int ret; + + switch (cmd) { + case FS_IOC_GETFLAGS: + flags = fi->i_flags & FS_FL_USER_VISIBLE; + return put_user(flags, (int __user *) arg); + case FS_IOC_SETFLAGS: + { + unsigned int oldflags; + + ret = mnt_want_write(filp->f_path.mnt); + if (ret) + return ret; + + if (!inode_owner_or_capable(inode)) { + ret = -EACCES; + goto out; + } + + if (get_user(flags, (int __user *) arg)) { + ret = -EFAULT; + goto out; + } + + flags = f2fs_mask_flags(inode->i_mode, flags); + + mutex_lock(&inode->i_mutex); + + oldflags = fi->i_flags; + + if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) { + if (!capable(CAP_LINUX_IMMUTABLE)) { + mutex_unlock(&inode->i_mutex); + ret = -EPERM; + goto out; + } + } + + flags = flags & FS_FL_USER_MODIFIABLE; + flags |= oldflags & ~FS_FL_USER_MODIFIABLE; + fi->i_flags = flags; + mutex_unlock(&inode->i_mutex); + + f2fs_set_inode_flags(inode); + inode->i_ctime = CURRENT_TIME; + mark_inode_dirty(inode); +out: + mnt_drop_write(filp->f_path.mnt); + return ret; + } + default: + return -ENOTTY; + } +} + +const struct file_operations f2fs_file_operations = { + .llseek = generic_file_llseek, + .read = do_sync_read, + .write = do_sync_write, + .aio_read = generic_file_aio_read, + .aio_write = generic_file_aio_write, + .open = generic_file_open, + .mmap = f2fs_file_mmap, + .fsync = f2fs_sync_file, + .fallocate = f2fs_fallocate, + .unlocked_ioctl = f2fs_ioctl, + .splice_read = generic_file_splice_read, + .splice_write = generic_file_splice_write, +}; -- cgit v1.2.3 From 0a8165d7c2cf1395059db20ab07665baf3758fcd Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Thu, 29 Nov 2012 13:28:09 +0900 Subject: f2fs: adjust kernel coding style As pointed out by Randy Dunlap, this patch removes all usage of "/**" for comment blocks. Instead, just use "/*". Signed-off-by: Jaegeuk Kim --- fs/f2fs/acl.c | 2 +- fs/f2fs/acl.h | 2 +- fs/f2fs/checkpoint.c | 10 +++++----- fs/f2fs/data.c | 12 ++++++------ fs/f2fs/debug.c | 6 +++--- fs/f2fs/dir.c | 4 ++-- fs/f2fs/f2fs.h | 2 +- fs/f2fs/file.c | 2 +- fs/f2fs/gc.c | 10 +++++----- fs/f2fs/gc.h | 4 ++-- fs/f2fs/hash.c | 2 +- fs/f2fs/inode.c | 4 ++-- fs/f2fs/namei.c | 4 ++-- fs/f2fs/node.c | 22 +++++++++++----------- fs/f2fs/node.h | 2 +- fs/f2fs/recovery.c | 2 +- fs/f2fs/segment.c | 26 +++++++++++++------------- fs/f2fs/segment.h | 2 +- fs/f2fs/super.c | 2 +- fs/f2fs/xattr.c | 2 +- fs/f2fs/xattr.h | 4 ++-- 21 files changed, 63 insertions(+), 63 deletions(-) (limited to 'fs/f2fs/file.c') diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c index dff2a2bfa755..1ac9a4b24f6e 100644 --- a/fs/f2fs/acl.c +++ b/fs/f2fs/acl.c @@ -1,4 +1,4 @@ -/** +/* * fs/f2fs/acl.c * * Copyright (c) 2012 Samsung Electronics Co., Ltd. diff --git a/fs/f2fs/acl.h b/fs/f2fs/acl.h index c97675e18fe2..80f430674417 100644 --- a/fs/f2fs/acl.h +++ b/fs/f2fs/acl.h @@ -1,4 +1,4 @@ -/** +/* * fs/f2fs/acl.h * * Copyright (c) 2012 Samsung Electronics Co., Ltd. diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 7c18f8efaadc..6ef36c37e2be 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -1,4 +1,4 @@ -/** +/* * fs/f2fs/checkpoint.c * * Copyright (c) 2012 Samsung Electronics Co., Ltd. @@ -24,7 +24,7 @@ static struct kmem_cache *orphan_entry_slab; static struct kmem_cache *inode_entry_slab; -/** +/* * We guarantee no failure on the returned page. */ struct page *grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index) @@ -44,7 +44,7 @@ repeat: return page; } -/** +/* * We guarantee no failure on the returned page. */ struct page *get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index) @@ -543,7 +543,7 @@ retry: goto retry; } -/** +/* * Freeze all the FS-operations for checkpoint. */ void block_operations(struct f2fs_sb_info *sbi) @@ -727,7 +727,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount) F2FS_RESET_SB_DIRT(sbi); } -/** +/* * We guarantee that this checkpoint procedure should not fail. */ void write_checkpoint(struct f2fs_sb_info *sbi, bool blocked, bool is_umount) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 5635cc5a9d4d..444c2a6fbaa0 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1,4 +1,4 @@ -/** +/* * fs/f2fs/data.c * * Copyright (c) 2012 Samsung Electronics Co., Ltd. @@ -21,7 +21,7 @@ #include "node.h" #include "segment.h" -/** +/* * Lock ordering for the change of data block address: * ->data_page * ->node_page @@ -207,7 +207,7 @@ struct page *find_data_page(struct inode *inode, pgoff_t index) return page; } -/** +/* * If it tries to access a hole, return an error. * Because, the callers, functions in dir.c and GC, should be able to know * whether this page exists or not. @@ -247,7 +247,7 @@ struct page *get_lock_data_page(struct inode *inode, pgoff_t index) return page; } -/** +/* * Caller ensures that this data page is never allocated. * A new zero-filled data page is allocated in the page cache. */ @@ -322,7 +322,7 @@ static void read_end_io(struct bio *bio, int err) bio_put(bio); } -/** +/* * Fill the locked page with data located in the block address. * Read operation is synchronous, and caller must unlock the page. */ @@ -367,7 +367,7 @@ int f2fs_readpage(struct f2fs_sb_info *sbi, struct page *page, return 0; } -/** +/* * This function should be used by the data read flow only where it * does not check the "create" flag that indicates block allocation. * The reason for this special functionality is to exploit VFS readahead diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index fb62960a1dc1..0e0380a588ad 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c @@ -1,4 +1,4 @@ -/** +/* * f2fs debugging statistics * * Copyright (c) 2012 Samsung Electronics Co., Ltd. @@ -78,7 +78,7 @@ static void update_general_status(struct f2fs_sb_info *sbi) } } -/** +/* * This function calculates BDF of every segments */ static void update_sit_info(struct f2fs_sb_info *sbi) @@ -113,7 +113,7 @@ static void update_sit_info(struct f2fs_sb_info *sbi) si->avg_vblocks = 0; } -/** +/* * This function calculates memory footprint. */ static void update_mem_info(struct f2fs_sb_info *sbi) diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 5ec7a06120e1..089eb6766890 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -1,4 +1,4 @@ -/** +/* * fs/f2fs/dir.c * * Copyright (c) 2012 Samsung Electronics Co., Ltd. @@ -453,7 +453,7 @@ fail: return err; } -/** +/* * It only removes the dentry from the dentry page,corresponding name * entry in name page does not need to be touched during deletion. */ diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 8d7fde1bda1e..8c3f1ef6ace2 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1,4 +1,4 @@ -/** +/* * fs/f2fs/f2fs.h * * Copyright (c) 2012 Samsung Electronics Co., Ltd. diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index f5ae36d19f4f..c1a108ffbfcc 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1,4 +1,4 @@ -/** +/* * fs/f2fs/file.c * * Copyright (c) 2012 Samsung Electronics Co., Ltd. diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 46774ce3ae03..3271be42c0b6 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -1,4 +1,4 @@ -/** +/* * fs/f2fs/gc.c * * Copyright (c) 2012 Samsung Electronics Co., Ltd. @@ -213,7 +213,7 @@ static unsigned int get_gc_cost(struct f2fs_sb_info *sbi, unsigned int segno, return get_cb_cost(sbi, segno); } -/** +/* * This function is called from two pathes. * One is garbage collection and the other is SSR segment selection. * When it is called during GC, it just gets a victim segment @@ -359,7 +359,7 @@ static int check_valid_map(struct f2fs_sb_info *sbi, return ret ? GC_OK : GC_NEXT; } -/** +/* * This function compares node address got in summary with that in NAT. * On validity, copy that node with cold status, otherwise (invalid node) * ignore that. @@ -425,7 +425,7 @@ next_step: return GC_DONE; } -/** +/* * Calculate start block index that this node page contains */ block_t start_bidx_of_node(unsigned int node_ofs) @@ -516,7 +516,7 @@ out: f2fs_put_page(page, 1); } -/** +/* * This function tries to get parent node of victim data block, and identifies * data block validity. If the block is valid, copy that with cold status and * modify parent node. diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h index cf42a554ca0a..b026d9354ccd 100644 --- a/fs/f2fs/gc.h +++ b/fs/f2fs/gc.h @@ -1,4 +1,4 @@ -/** +/* * fs/f2fs/gc.h * * Copyright (c) 2012 Samsung Electronics Co., Ltd. @@ -42,7 +42,7 @@ struct inode_entry { struct inode *inode; }; -/** +/* * inline functions */ static inline block_t free_user_blocks(struct f2fs_sb_info *sbi) diff --git a/fs/f2fs/hash.c b/fs/f2fs/hash.c index beb155e8d06d..a60f04200f8b 100644 --- a/fs/f2fs/hash.c +++ b/fs/f2fs/hash.c @@ -1,4 +1,4 @@ -/** +/* * fs/f2fs/hash.c * * Copyright (c) 2012 Samsung Electronics Co., Ltd. diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 94f13d2815e9..aa4ef4f48ffd 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -1,4 +1,4 @@ -/** +/* * fs/f2fs/inode.c * * Copyright (c) 2012 Samsung Electronics Co., Ltd. @@ -235,7 +235,7 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) return 0; } -/** +/* * Called at the last iput() if i_nlink is zero */ void f2fs_evict_inode(struct inode *inode) diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index aec362f6f0b0..63efd77fab92 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -1,4 +1,4 @@ -/** +/* * fs/f2fs/namei.c * * Copyright (c) 2012 Samsung Electronics Co., Ltd. @@ -96,7 +96,7 @@ static int is_multimedia_file(const unsigned char *s, const char *sub) return ret; } -/** +/* * Set multimedia files as cold files for hot/cold data separation */ static inline void set_cold_file(struct f2fs_sb_info *sbi, struct inode *inode, diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 5d421fe22575..25d303646da7 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1,4 +1,4 @@ -/** +/* * fs/f2fs/node.c * * Copyright (c) 2012 Samsung Electronics Co., Ltd. @@ -81,7 +81,7 @@ static struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid) return dst_page; } -/** +/* * Readahead NAT pages */ static void ra_nat_pages(struct f2fs_sb_info *sbi, int nid) @@ -251,7 +251,7 @@ static int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink) return nr_shrink; } -/** +/* * This function returns always success */ void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni) @@ -302,7 +302,7 @@ cache: cache_nat_entry(NM_I(sbi), nid, &ne); } -/** +/* * The maximum depth is four. * Offset[0] will have raw inode offset. */ @@ -649,7 +649,7 @@ fail: return err; } -/** +/* * All the block addresses of data and nodes should be nullified. */ int truncate_inode_blocks(struct inode *inode, pgoff_t from) @@ -860,7 +860,7 @@ static int read_node_page(struct page *page, int type) return f2fs_readpage(sbi, page, ni.blk_addr, type); } -/** +/* * Readahead a node page */ void ra_node_page(struct f2fs_sb_info *sbi, nid_t nid) @@ -910,7 +910,7 @@ struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid) return page; } -/** +/* * Return a locked page for the desired node page. * And, readahead MAX_RA_NODE number of node pages. */ @@ -1186,7 +1186,7 @@ static int f2fs_release_node_page(struct page *page, gfp_t wait) return 0; } -/** +/* * Structure of the f2fs node operations */ const struct address_space_operations f2fs_node_aops = { @@ -1386,7 +1386,7 @@ retry: return true; } -/** +/* * alloc_nid() should be called prior to this function. */ void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid) @@ -1403,7 +1403,7 @@ void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid) spin_unlock(&nm_i->free_nid_list_lock); } -/** +/* * alloc_nid() should be called prior to this function. */ void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid) @@ -1545,7 +1545,7 @@ retry: return true; } -/** +/* * This function is called during the checkpointing process. */ void flush_nat_entries(struct f2fs_sb_info *sbi) diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h index 0ab92d643052..afdb130f782e 100644 --- a/fs/f2fs/node.h +++ b/fs/f2fs/node.h @@ -1,4 +1,4 @@ -/** +/* * fs/f2fs/node.h * * Copyright (c) 2012 Samsung Electronics Co., Ltd. diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index 222a7bb92214..b07e9b6ef376 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c @@ -1,4 +1,4 @@ -/** +/* * fs/f2fs/recovery.c * * Copyright (c) 2012 Samsung Electronics Co., Ltd. diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index d973c56e8bd6..a177eb387d38 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -1,4 +1,4 @@ -/** +/* * fs/f2fs/segment.c * * Copyright (c) 2012 Samsung Electronics Co., Ltd. @@ -36,7 +36,7 @@ static int need_to_flush(struct f2fs_sb_info *sbi) return 0; } -/** +/* * This function balances dirty node and dentry pages. * In addition, it controls garbage collection. */ @@ -105,7 +105,7 @@ static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, } } -/** +/* * Should not occur error such as -ENOMEM. * Adding dirty entry into seglist is not critical operation. * If a given segment is one of current working segments, it won't be added. @@ -136,7 +136,7 @@ void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno) return; } -/** +/* * Should call clear_prefree_segments after checkpoint is done. */ static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi) @@ -269,7 +269,7 @@ void invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr) mutex_unlock(&sit_i->sentry_lock); } -/** +/* * This function should be resided under the curseg_mutex lock */ static void __add_sum_entry(struct f2fs_sb_info *sbi, int type, @@ -282,7 +282,7 @@ static void __add_sum_entry(struct f2fs_sb_info *sbi, int type, return; } -/** +/* * Calculate the number of current summary pages for writing */ int npages_for_summary_flush(struct f2fs_sb_info *sbi) @@ -309,7 +309,7 @@ int npages_for_summary_flush(struct f2fs_sb_info *sbi) return 3; } -/** +/* * Caller should put this summary page */ struct page *get_sum_page(struct f2fs_sb_info *sbi, unsigned int segno) @@ -371,7 +371,7 @@ next: return NULL_SEGNO; } -/** +/* * Find a new segment from the free segments bitmap to right order * This function should be returned with success, otherwise BUG */ @@ -483,7 +483,7 @@ static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified) __set_sit_entry_type(sbi, type, curseg->segno, modified); } -/** +/* * Allocate a current working segment. * This function always allocates a free segment in LFS manner. */ @@ -520,7 +520,7 @@ static void __next_free_blkoff(struct f2fs_sb_info *sbi, seg->next_blkoff = ofs; } -/** +/* * If a segment is written by LFS manner, next block offset is just obtained * by increasing the current block offset. However, if a segment is written by * SSR manner, next block offset obtained by calling __next_free_blkoff @@ -534,7 +534,7 @@ static void __refresh_next_blkoff(struct f2fs_sb_info *sbi, seg->next_blkoff++; } -/** +/* * This function always allocates a used segment (from dirty seglist) by SSR * manner, so it should recover the existing segment information of valid blocks */ @@ -1310,7 +1310,7 @@ static bool flush_sits_in_journal(struct f2fs_sb_info *sbi) return 0; } -/** +/* * CP calls this function, which flushes SIT entries including sit_journal, * and moves prefree segs to free segs. */ @@ -1624,7 +1624,7 @@ static int build_dirty_segmap(struct f2fs_sb_info *sbi) return init_victim_segmap(sbi); } -/** +/* * Update min, max modified time for cost-benefit GC algorithm */ static void init_min_max_mtime(struct f2fs_sb_info *sbi) diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index e380a8ef13f5..2c445f8947c9 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -1,4 +1,4 @@ -/** +/* * fs/f2fs/segment.h * * Copyright (c) 2012 Samsung Electronics Co., Ltd. diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 878bf382f848..4360600c81e8 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1,4 +1,4 @@ -/** +/* * fs/f2fs/super.c * * Copyright (c) 2012 Samsung Electronics Co., Ltd. diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index aca50fe163f6..5324d1e9d168 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -1,4 +1,4 @@ -/** +/* * fs/f2fs/xattr.c * * Copyright (c) 2012 Samsung Electronics Co., Ltd. diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h index 29b0a08e1e14..49c9558305e3 100644 --- a/fs/f2fs/xattr.h +++ b/fs/f2fs/xattr.h @@ -1,4 +1,4 @@ -/** +/* * fs/f2fs/xattr.h * * Copyright (c) 2012 Samsung Electronics Co., Ltd. @@ -77,7 +77,7 @@ struct f2fs_xattr_entry { #define MAX_VALUE_LEN (MIN_OFFSET - sizeof(struct f2fs_xattr_header) - \ sizeof(struct f2fs_xattr_entry)) -/** +/* * On-disk structure of f2fs_xattr * We use only 1 block for xattr. * -- cgit v1.2.3 From 1fa95b0b6798164a31c1048efdf62b71038eb3d5 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Sat, 1 Dec 2012 10:56:01 +0900 Subject: f2fs: check read only condition before beginning write out If the filesystem is mounted as read-only then return from that point itself instead of first doing a writeout/wait and then checking for read-only condition. Signed-off-by: Namjae Jeon Signed-off-by: Amit Sahrawat --- fs/f2fs/file.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'fs/f2fs/file.c') diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index c1a108ffbfcc..89241c50eb96 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -132,14 +132,15 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) .for_reclaim = 0, }; + if (inode->i_sb->s_flags & MS_RDONLY) + return 0; + ret = filemap_write_and_wait_range(inode->i_mapping, start, end); if (ret) return ret; mutex_lock(&inode->i_mutex); - if (inode->i_sb->s_flags & MS_RDONLY) - goto out; if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) goto out; -- cgit v1.2.3 From 705f814e34e08f6169439014a2916fd5afbdf232 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 2 Dec 2012 08:11:38 -0500 Subject: f2fs: remove unused variable The variables node_page and page_offset are initialized but never used otherwise, so remove those unused variables. Signed-off-by: Wei Yongjun --- fs/f2fs/dir.c | 2 -- fs/f2fs/file.c | 2 -- 2 files changed, 4 deletions(-) (limited to 'fs/f2fs/file.c') diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 089eb6766890..2a20c504ecd8 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -509,13 +509,11 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, } if (bit_pos == NR_DENTRY_IN_BLOCK) { - loff_t page_offset; truncate_hole(dir, page->index, page->index + 1); clear_page_dirty_for_io(page); ClearPageUptodate(page); dec_page_count(sbi, F2FS_DIRTY_DENTS); inode_dec_dirty_dents(dir); - page_offset = page->index << PAGE_CACHE_SHIFT; f2fs_put_page(page, 1); } else { f2fs_put_page(page, 1); diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 89241c50eb96..f9e085dfb1f0 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -30,7 +30,6 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page = vmf->page; struct inode *inode = vma->vm_file->f_path.dentry->d_inode; struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); - struct page *node_page; block_t old_blk_addr; struct dnode_of_data dn; int err; @@ -50,7 +49,6 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma, } old_blk_addr = dn.data_blkaddr; - node_page = dn.node_page; if (old_blk_addr == NULL_ADDR) { err = reserve_new_block(&dn); -- cgit v1.2.3