diff options
Diffstat (limited to 'fs/exofs')
| -rw-r--r-- | fs/exofs/Kbuild | 2 | ||||
| -rw-r--r-- | fs/exofs/exofs.h | 14 | ||||
| -rw-r--r-- | fs/exofs/file.c | 87 | ||||
| -rw-r--r-- | fs/exofs/inode.c | 148 | 
4 files changed, 250 insertions, 1 deletions
diff --git a/fs/exofs/Kbuild b/fs/exofs/Kbuild index 36d23ca79a58..c9546edaddeb 100644 --- a/fs/exofs/Kbuild +++ b/fs/exofs/Kbuild @@ -12,5 +12,5 @@  # Kbuild - Gets included from the Kernels Makefile and build system  # -exofs-y := osd.o +exofs-y := osd.o inode.o file.o  obj-$(CONFIG_EXOFS_FS) += exofs.o diff --git a/fs/exofs/exofs.h b/fs/exofs/exofs.h index 365376d3f72d..a735258c7364 100644 --- a/fs/exofs/exofs.h +++ b/fs/exofs/exofs.h @@ -124,4 +124,18 @@ static inline struct exofs_i_info *exofs_i(struct inode *inode)  	return container_of(inode, struct exofs_i_info, vfs_inode);  } +/************************* + * function declarations * + *************************/ +/* inode.c               */ +void exofs_truncate(struct inode *inode); +int exofs_setattr(struct dentry *, struct iattr *); + +/********************* + * operation vectors * + *********************/ +/* file.c            */ +extern const struct inode_operations exofs_file_inode_operations; +extern const struct file_operations exofs_file_operations; +  #endif diff --git a/fs/exofs/file.c b/fs/exofs/file.c new file mode 100644 index 000000000000..6ed7fe484752 --- /dev/null +++ b/fs/exofs/file.c @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2005, 2006 + * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) + * Copyright (C) 2005, 2006 + * International Business Machines + * Copyright (C) 2008, 2009 + * Boaz Harrosh <bharrosh@panasas.com> + * + * Copyrights for code taken from ext2: + *     Copyright (C) 1992, 1993, 1994, 1995 + *     Remy Card (card@masi.ibp.fr) + *     Laboratoire MASI - Institut Blaise Pascal + *     Universite Pierre et Marie Curie (Paris VI) + *     from + *     linux/fs/minix/inode.c + *     Copyright (C) 1991, 1992  Linus Torvalds + * + * This file is part of exofs. + * + * exofs 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.  Since it is based on ext2, and the only + * valid version of GPL for the Linux kernel is version 2, the only valid + * version of GPL for exofs is version 2. + * + * exofs 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 exofs; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA + */ + +#include <linux/buffer_head.h> + +#include "exofs.h" + +static int exofs_release_file(struct inode *inode, struct file *filp) +{ +	return 0; +} + +static int exofs_file_fsync(struct file *filp, struct dentry *dentry, +			    int datasync) +{ +	int ret; +	struct address_space *mapping = filp->f_mapping; + +	ret = filemap_write_and_wait(mapping); +	if (ret) +		return ret; + +	/*Note: file_fsync below also calles sync_blockdev, which is a no-op +	 *      for exofs, but other then that it does sync_inode and +	 *      sync_superblock which is what we need here. +	 */ +	return file_fsync(filp, dentry, datasync); +} + +static int exofs_flush(struct file *file, fl_owner_t id) +{ +	exofs_file_fsync(file, file->f_path.dentry, 1); +	/* TODO: Flush the OSD target */ +	return 0; +} + +const struct file_operations exofs_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, +	.mmap		= generic_file_mmap, +	.open		= generic_file_open, +	.release	= exofs_release_file, +	.fsync		= exofs_file_fsync, +	.flush		= exofs_flush, +	.splice_read	= generic_file_splice_read, +	.splice_write	= generic_file_splice_write, +}; + +const struct inode_operations exofs_file_inode_operations = { +	.truncate	= exofs_truncate, +	.setattr	= exofs_setattr, +}; diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c new file mode 100644 index 000000000000..b0bda1e91225 --- /dev/null +++ b/fs/exofs/inode.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2005, 2006 + * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) + * Copyright (C) 2005, 2006 + * International Business Machines + * Copyright (C) 2008, 2009 + * Boaz Harrosh <bharrosh@panasas.com> + * + * Copyrights for code taken from ext2: + *     Copyright (C) 1992, 1993, 1994, 1995 + *     Remy Card (card@masi.ibp.fr) + *     Laboratoire MASI - Institut Blaise Pascal + *     Universite Pierre et Marie Curie (Paris VI) + *     from + *     linux/fs/minix/inode.c + *     Copyright (C) 1991, 1992  Linus Torvalds + * + * This file is part of exofs. + * + * exofs 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.  Since it is based on ext2, and the only + * valid version of GPL for the Linux kernel is version 2, the only valid + * version of GPL for exofs is version 2. + * + * exofs 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 exofs; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA + */ + +#include <linux/writeback.h> +#include <linux/buffer_head.h> + +#include "exofs.h" + +#ifdef CONFIG_EXOFS_DEBUG +#  define EXOFS_DEBUG_OBJ_ISIZE 1 +#endif + +/****************************************************************************** + * INODE OPERATIONS + *****************************************************************************/ + +/* + * Test whether an inode is a fast symlink. + */ +static inline int exofs_inode_is_fast_symlink(struct inode *inode) +{ +	struct exofs_i_info *oi = exofs_i(inode); + +	return S_ISLNK(inode->i_mode) && (oi->i_data[0] != 0); +} + +/* + * get_block_t - Fill in a buffer_head + * An OSD takes care of block allocation so we just fake an allocation by + * putting in the inode's sector_t in the buffer_head. + * TODO: What about the case of create==0 and @iblock does not exist in the + * object? + */ +static int exofs_get_block(struct inode *inode, sector_t iblock, +		    struct buffer_head *bh_result, int create) +{ +	map_bh(bh_result, inode->i_sb, iblock); +	return 0; +} + +const struct osd_attr g_attr_logical_length = ATTR_DEF( +	OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8); + +/* + * Truncate a file to the specified size - all we have to do is set the size + * attribute.  We make sure the object exists first. + */ +void exofs_truncate(struct inode *inode) +{ +	struct exofs_sb_info *sbi = inode->i_sb->s_fs_info; +	struct exofs_i_info *oi = exofs_i(inode); +	struct osd_obj_id obj = {sbi->s_pid, inode->i_ino + EXOFS_OBJ_OFF}; +	struct osd_request *or; +	struct osd_attr attr; +	loff_t isize = i_size_read(inode); +	__be64 newsize; +	int ret; + +	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) +	     || S_ISLNK(inode->i_mode))) +		return; +	if (exofs_inode_is_fast_symlink(inode)) +		return; +	if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) +		return; +	inode->i_mtime = inode->i_ctime = CURRENT_TIME; + +	nobh_truncate_page(inode->i_mapping, isize, exofs_get_block); + +	or = osd_start_request(sbi->s_dev, GFP_KERNEL); +	if (unlikely(!or)) { +		EXOFS_ERR("ERROR: exofs_truncate: osd_start_request failed\n"); +		goto fail; +	} + +	osd_req_set_attributes(or, &obj); + +	newsize = cpu_to_be64((u64)isize); +	attr = g_attr_logical_length; +	attr.val_ptr = &newsize; +	osd_req_add_set_attr_list(or, &attr, 1); + +	/* if we are about to truncate an object, and it hasn't been +	 * created yet, wait +	 */ +	if (unlikely(wait_obj_created(oi))) +		goto fail; + +	ret = exofs_sync_op(or, sbi->s_timeout, oi->i_cred); +	osd_end_request(or); +	if (ret) +		goto fail; + +out: +	mark_inode_dirty(inode); +	return; +fail: +	make_bad_inode(inode); +	goto out; +} + +/* + * Set inode attributes - just call generic functions. + */ +int exofs_setattr(struct dentry *dentry, struct iattr *iattr) +{ +	struct inode *inode = dentry->d_inode; +	int error; + +	error = inode_change_ok(inode, iattr); +	if (error) +		return error; + +	error = inode_setattr(inode, iattr); +	return error; +}  |