diff options
author | Boaz Harrosh <bharrosh@panasas.com> | 2008-10-27 12:37:02 -0400 |
---|---|---|
committer | Boaz Harrosh <bharrosh@panasas.com> | 2009-03-31 12:44:24 -0400 |
commit | e806271916ed6068a0e3e4e9298dff0688b88e0d (patch) | |
tree | 53669f4a55fecd82d289c035712d416e5b8dce35 | |
parent | b14f8ab2844987f013253dd04b708bde7fc1b52d (diff) |
exofs: file and file_inode operations
implementation of the file_operations and inode_operations for
regular data files.
Most file_operations are generic vfs implementations except:
- exofs_truncate will truncate the OSD object as well
- Generic file_fsync is not good for none_bd devices so open code it
- The default for .flush in Linux is todo nothing so call exofs_fsync
on the file.
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
-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 @@ | |||
12 | # Kbuild - Gets included from the Kernels Makefile and build system | 12 | # Kbuild - Gets included from the Kernels Makefile and build system |
13 | # | 13 | # |
14 | 14 | ||
15 | exofs-y := osd.o | 15 | exofs-y := osd.o inode.o file.o |
16 | obj-$(CONFIG_EXOFS_FS) += exofs.o | 16 | 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) | |||
124 | return container_of(inode, struct exofs_i_info, vfs_inode); | 124 | return container_of(inode, struct exofs_i_info, vfs_inode); |
125 | } | 125 | } |
126 | 126 | ||
127 | /************************* | ||
128 | * function declarations * | ||
129 | *************************/ | ||
130 | /* inode.c */ | ||
131 | void exofs_truncate(struct inode *inode); | ||
132 | int exofs_setattr(struct dentry *, struct iattr *); | ||
133 | |||
134 | /********************* | ||
135 | * operation vectors * | ||
136 | *********************/ | ||
137 | /* file.c */ | ||
138 | extern const struct inode_operations exofs_file_inode_operations; | ||
139 | extern const struct file_operations exofs_file_operations; | ||
140 | |||
127 | #endif | 141 | #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 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005, 2006 | ||
3 | * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) | ||
4 | * Copyright (C) 2005, 2006 | ||
5 | * International Business Machines | ||
6 | * Copyright (C) 2008, 2009 | ||
7 | * Boaz Harrosh <bharrosh@panasas.com> | ||
8 | * | ||
9 | * Copyrights for code taken from ext2: | ||
10 | * Copyright (C) 1992, 1993, 1994, 1995 | ||
11 | * Remy Card (card@masi.ibp.fr) | ||
12 | * Laboratoire MASI - Institut Blaise Pascal | ||
13 | * Universite Pierre et Marie Curie (Paris VI) | ||
14 | * from | ||
15 | * linux/fs/minix/inode.c | ||
16 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
17 | * | ||
18 | * This file is part of exofs. | ||
19 | * | ||
20 | * exofs is free software; you can redistribute it and/or modify | ||
21 | * it under the terms of the GNU General Public License as published by | ||
22 | * the Free Software Foundation. Since it is based on ext2, and the only | ||
23 | * valid version of GPL for the Linux kernel is version 2, the only valid | ||
24 | * version of GPL for exofs is version 2. | ||
25 | * | ||
26 | * exofs is distributed in the hope that it will be useful, | ||
27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
29 | * GNU General Public License for more details. | ||
30 | * | ||
31 | * You should have received a copy of the GNU General Public License | ||
32 | * along with exofs; if not, write to the Free Software | ||
33 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
34 | */ | ||
35 | |||
36 | #include <linux/buffer_head.h> | ||
37 | |||
38 | #include "exofs.h" | ||
39 | |||
40 | static int exofs_release_file(struct inode *inode, struct file *filp) | ||
41 | { | ||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | static int exofs_file_fsync(struct file *filp, struct dentry *dentry, | ||
46 | int datasync) | ||
47 | { | ||
48 | int ret; | ||
49 | struct address_space *mapping = filp->f_mapping; | ||
50 | |||
51 | ret = filemap_write_and_wait(mapping); | ||
52 | if (ret) | ||
53 | return ret; | ||
54 | |||
55 | /*Note: file_fsync below also calles sync_blockdev, which is a no-op | ||
56 | * for exofs, but other then that it does sync_inode and | ||
57 | * sync_superblock which is what we need here. | ||
58 | */ | ||
59 | return file_fsync(filp, dentry, datasync); | ||
60 | } | ||
61 | |||
62 | static int exofs_flush(struct file *file, fl_owner_t id) | ||
63 | { | ||
64 | exofs_file_fsync(file, file->f_path.dentry, 1); | ||
65 | /* TODO: Flush the OSD target */ | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | const struct file_operations exofs_file_operations = { | ||
70 | .llseek = generic_file_llseek, | ||
71 | .read = do_sync_read, | ||
72 | .write = do_sync_write, | ||
73 | .aio_read = generic_file_aio_read, | ||
74 | .aio_write = generic_file_aio_write, | ||
75 | .mmap = generic_file_mmap, | ||
76 | .open = generic_file_open, | ||
77 | .release = exofs_release_file, | ||
78 | .fsync = exofs_file_fsync, | ||
79 | .flush = exofs_flush, | ||
80 | .splice_read = generic_file_splice_read, | ||
81 | .splice_write = generic_file_splice_write, | ||
82 | }; | ||
83 | |||
84 | const struct inode_operations exofs_file_inode_operations = { | ||
85 | .truncate = exofs_truncate, | ||
86 | .setattr = exofs_setattr, | ||
87 | }; | ||
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 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005, 2006 | ||
3 | * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) | ||
4 | * Copyright (C) 2005, 2006 | ||
5 | * International Business Machines | ||
6 | * Copyright (C) 2008, 2009 | ||
7 | * Boaz Harrosh <bharrosh@panasas.com> | ||
8 | * | ||
9 | * Copyrights for code taken from ext2: | ||
10 | * Copyright (C) 1992, 1993, 1994, 1995 | ||
11 | * Remy Card (card@masi.ibp.fr) | ||
12 | * Laboratoire MASI - Institut Blaise Pascal | ||
13 | * Universite Pierre et Marie Curie (Paris VI) | ||
14 | * from | ||
15 | * linux/fs/minix/inode.c | ||
16 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
17 | * | ||
18 | * This file is part of exofs. | ||
19 | * | ||
20 | * exofs is free software; you can redistribute it and/or modify | ||
21 | * it under the terms of the GNU General Public License as published by | ||
22 | * the Free Software Foundation. Since it is based on ext2, and the only | ||
23 | * valid version of GPL for the Linux kernel is version 2, the only valid | ||
24 | * version of GPL for exofs is version 2. | ||
25 | * | ||
26 | * exofs is distributed in the hope that it will be useful, | ||
27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
29 | * GNU General Public License for more details. | ||
30 | * | ||
31 | * You should have received a copy of the GNU General Public License | ||
32 | * along with exofs; if not, write to the Free Software | ||
33 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
34 | */ | ||
35 | |||
36 | #include <linux/writeback.h> | ||
37 | #include <linux/buffer_head.h> | ||
38 | |||
39 | #include "exofs.h" | ||
40 | |||
41 | #ifdef CONFIG_EXOFS_DEBUG | ||
42 | # define EXOFS_DEBUG_OBJ_ISIZE 1 | ||
43 | #endif | ||
44 | |||
45 | /****************************************************************************** | ||
46 | * INODE OPERATIONS | ||
47 | *****************************************************************************/ | ||
48 | |||
49 | /* | ||
50 | * Test whether an inode is a fast symlink. | ||
51 | */ | ||
52 | static inline int exofs_inode_is_fast_symlink(struct inode *inode) | ||
53 | { | ||
54 | struct exofs_i_info *oi = exofs_i(inode); | ||
55 | |||
56 | return S_ISLNK(inode->i_mode) && (oi->i_data[0] != 0); | ||
57 | } | ||
58 | |||
59 | /* | ||
60 | * get_block_t - Fill in a buffer_head | ||
61 | * An OSD takes care of block allocation so we just fake an allocation by | ||
62 | * putting in the inode's sector_t in the buffer_head. | ||
63 | * TODO: What about the case of create==0 and @iblock does not exist in the | ||
64 | * object? | ||
65 | */ | ||
66 | static int exofs_get_block(struct inode *inode, sector_t iblock, | ||
67 | struct buffer_head *bh_result, int create) | ||
68 | { | ||
69 | map_bh(bh_result, inode->i_sb, iblock); | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | const struct osd_attr g_attr_logical_length = ATTR_DEF( | ||
74 | OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8); | ||
75 | |||
76 | /* | ||
77 | * Truncate a file to the specified size - all we have to do is set the size | ||
78 | * attribute. We make sure the object exists first. | ||
79 | */ | ||
80 | void exofs_truncate(struct inode *inode) | ||
81 | { | ||
82 | struct exofs_sb_info *sbi = inode->i_sb->s_fs_info; | ||
83 | struct exofs_i_info *oi = exofs_i(inode); | ||
84 | struct osd_obj_id obj = {sbi->s_pid, inode->i_ino + EXOFS_OBJ_OFF}; | ||
85 | struct osd_request *or; | ||
86 | struct osd_attr attr; | ||
87 | loff_t isize = i_size_read(inode); | ||
88 | __be64 newsize; | ||
89 | int ret; | ||
90 | |||
91 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) | ||
92 | || S_ISLNK(inode->i_mode))) | ||
93 | return; | ||
94 | if (exofs_inode_is_fast_symlink(inode)) | ||
95 | return; | ||
96 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) | ||
97 | return; | ||
98 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
99 | |||
100 | nobh_truncate_page(inode->i_mapping, isize, exofs_get_block); | ||
101 | |||
102 | or = osd_start_request(sbi->s_dev, GFP_KERNEL); | ||
103 | if (unlikely(!or)) { | ||
104 | EXOFS_ERR("ERROR: exofs_truncate: osd_start_request failed\n"); | ||
105 | goto fail; | ||
106 | } | ||
107 | |||
108 | osd_req_set_attributes(or, &obj); | ||
109 | |||
110 | newsize = cpu_to_be64((u64)isize); | ||
111 | attr = g_attr_logical_length; | ||
112 | attr.val_ptr = &newsize; | ||
113 | osd_req_add_set_attr_list(or, &attr, 1); | ||
114 | |||
115 | /* if we are about to truncate an object, and it hasn't been | ||
116 | * created yet, wait | ||
117 | */ | ||
118 | if (unlikely(wait_obj_created(oi))) | ||
119 | goto fail; | ||
120 | |||
121 | ret = exofs_sync_op(or, sbi->s_timeout, oi->i_cred); | ||
122 | osd_end_request(or); | ||
123 | if (ret) | ||
124 | goto fail; | ||
125 | |||
126 | out: | ||
127 | mark_inode_dirty(inode); | ||
128 | return; | ||
129 | fail: | ||
130 | make_bad_inode(inode); | ||
131 | goto out; | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * Set inode attributes - just call generic functions. | ||
136 | */ | ||
137 | int exofs_setattr(struct dentry *dentry, struct iattr *iattr) | ||
138 | { | ||
139 | struct inode *inode = dentry->d_inode; | ||
140 | int error; | ||
141 | |||
142 | error = inode_change_ok(inode, iattr); | ||
143 | if (error) | ||
144 | return error; | ||
145 | |||
146 | error = inode_setattr(inode, iattr); | ||
147 | return error; | ||
148 | } | ||