]>
Commit | Line | Data |
---|---|---|
51f0bbe4 BB |
1 | /* |
2 | * CDDL HEADER START | |
3 | * | |
4 | * The contents of this file are subject to the terms of the | |
5 | * Common Development and Distribution License (the "License"). | |
6 | * You may not use this file except in compliance with the License. | |
7 | * | |
8 | * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | |
9 | * or http://www.opensolaris.org/os/licensing. | |
10 | * See the License for the specific language governing permissions | |
11 | * and limitations under the License. | |
12 | * | |
13 | * When distributing Covered Code, include this CDDL HEADER in each | |
14 | * file and include the License file at usr/src/OPENSOLARIS.LICENSE. | |
15 | * If applicable, add the following below this CDDL HEADER, with the | |
16 | * fields enclosed by brackets "[]" replaced with your own identifying | |
17 | * information: Portions Copyright [yyyy] [name of copyright owner] | |
18 | * | |
19 | * CDDL HEADER END | |
20 | */ | |
21 | /* | |
22 | * Copyright (c) 2011, Lawrence Livermore National Security, LLC. | |
23 | */ | |
24 | ||
25 | ||
26 | #include <sys/zfs_vfsops.h> | |
27 | #include <sys/zfs_vnops.h> | |
28 | #include <sys/zfs_znode.h> | |
29 | #include <sys/zpl.h> | |
30 | ||
31 | ||
32 | static struct inode * | |
33 | zpl_inode_alloc(struct super_block *sb) | |
34 | { | |
35 | struct inode *ip; | |
36 | ||
37 | VERIFY3S(zfs_inode_alloc(sb, &ip), ==, 0); | |
38 | ip->i_version = 1; | |
39 | ||
40 | return (ip); | |
41 | } | |
42 | ||
43 | static void | |
44 | zpl_inode_destroy(struct inode *ip) | |
45 | { | |
46 | ASSERT(atomic_read(&ip->i_count) == 0); | |
47 | zfs_inode_destroy(ip); | |
48 | } | |
49 | ||
2c395def BB |
50 | /* |
51 | * When ->drop_inode() is called its return value indicates if the | |
52 | * inode should be evicted from the inode cache. If the inode is | |
53 | * unhashed and has no links the default policy is to evict it | |
54 | * immediately. | |
55 | * | |
56 | * Prior to 2.6.36 this eviction was accomplished by the vfs calling | |
57 | * ->delete_inode(). It was ->delete_inode()'s responsibility to | |
58 | * truncate the inode pages and call clear_inode(). The call to | |
59 | * clear_inode() synchronously invalidates all the buffers and | |
60 | * calls ->clear_inode(). It was ->clear_inode()'s responsibility | |
61 | * to cleanup and filesystem specific data before freeing the inode. | |
62 | * | |
63 | * This elaborate mechanism was replaced by ->evict_inode() which | |
64 | * does the job of both ->delete_inode() and ->clear_inode(). It | |
65 | * will be called exactly once, and when it returns the inode must | |
66 | * be in a state where it can simply be freed. The ->evict_inode() | |
67 | * callback must minimally truncate the inode pages, and call | |
68 | * end_writeback() to complete all outstanding writeback for the | |
69 | * inode. After this is complete evict inode can cleanup any | |
70 | * remaining filesystem specific data. | |
71 | */ | |
72 | #ifdef HAVE_EVICT_INODE | |
51f0bbe4 | 73 | static void |
2c395def | 74 | zpl_evict_inode(struct inode *ip) |
51f0bbe4 | 75 | { |
2c395def BB |
76 | truncate_inode_pages(&ip->i_data, 0); |
77 | end_writeback(ip); | |
78 | zfs_inactive(ip); | |
51f0bbe4 BB |
79 | } |
80 | ||
2c395def BB |
81 | #else |
82 | ||
51f0bbe4 | 83 | static void |
2c395def | 84 | zpl_clear_inode(struct inode *ip) |
51f0bbe4 BB |
85 | { |
86 | zfs_inactive(ip); | |
87 | } | |
88 | ||
2c395def BB |
89 | static void |
90 | zpl_inode_delete(struct inode *ip) | |
91 | { | |
92 | truncate_inode_pages(&ip->i_data, 0); | |
93 | clear_inode(ip); | |
94 | } | |
95 | ||
96 | #endif /* HAVE_EVICT_INODE */ | |
97 | ||
51f0bbe4 BB |
98 | static void |
99 | zpl_put_super(struct super_block *sb) | |
100 | { | |
101 | int error; | |
102 | ||
103 | error = -zfs_umount(sb); | |
104 | ASSERT3S(error, <=, 0); | |
105 | } | |
106 | ||
03f9ba9d BB |
107 | static int |
108 | zpl_sync_fs(struct super_block *sb, int wait) | |
109 | { | |
110 | cred_t *cr; | |
111 | int error; | |
112 | ||
113 | cr = (cred_t *)get_current_cred(); | |
114 | error = -zfs_sync(sb, wait, cr); | |
115 | put_cred(cr); | |
116 | ASSERT3S(error, <=, 0); | |
117 | ||
118 | return (error); | |
119 | } | |
120 | ||
51f0bbe4 BB |
121 | static int |
122 | zpl_statfs(struct dentry *dentry, struct kstatfs *statp) | |
123 | { | |
124 | int error; | |
125 | ||
126 | error = -zfs_statvfs(dentry, statp); | |
127 | ASSERT3S(error, <=, 0); | |
128 | ||
129 | return (error); | |
130 | } | |
131 | ||
0de19dad BB |
132 | static int |
133 | zpl_remount_fs(struct super_block *sb, int *flags, char *data) | |
134 | { | |
135 | int error; | |
136 | error = -zfs_remount(sb, flags, data); | |
137 | ASSERT3S(error, <=, 0); | |
138 | ||
139 | return (error); | |
140 | } | |
141 | ||
51f0bbe4 BB |
142 | static int |
143 | zpl_show_options(struct seq_file *seq, struct vfsmount *vfsp) | |
144 | { | |
145 | struct super_block *sb = vfsp->mnt_sb; | |
146 | zfs_sb_t *zsb = sb->s_fs_info; | |
147 | ||
148 | /* | |
149 | * The Linux VFS automatically handles the following flags: | |
150 | * MNT_NOSUID, MNT_NODEV, MNT_NOEXEC, MNT_NOATIME, MNT_READONLY | |
151 | */ | |
152 | ||
153 | if (zsb->z_flags & ZSB_XATTR_USER) | |
154 | seq_printf(seq, ",%s", "xattr"); | |
155 | ||
156 | return (0); | |
157 | } | |
158 | ||
159 | static int | |
160 | zpl_fill_super(struct super_block *sb, void *data, int silent) | |
161 | { | |
162 | int error; | |
163 | ||
164 | error = -zfs_domount(sb, data, silent); | |
165 | ASSERT3S(error, <=, 0); | |
166 | ||
167 | return (error); | |
168 | } | |
169 | ||
170 | static int | |
171 | zpl_get_sb(struct file_system_type *fs_type, int flags, | |
172 | const char *osname, void *data, struct vfsmount *mnt) | |
173 | { | |
174 | zpl_mount_data_t zmd = { osname, data, mnt }; | |
175 | ||
176 | return get_sb_nodev(fs_type, flags, &zmd, zpl_fill_super, mnt); | |
177 | } | |
178 | ||
179 | static void | |
180 | zpl_kill_sb(struct super_block *sb) | |
181 | { | |
182 | #ifdef HAVE_SNAPSHOT | |
183 | zfs_sb_t *zsb = sb->s_fs_info; | |
184 | ||
185 | if (zsb && dmu_objset_is_snapshot(zsb->z_os)) | |
186 | zfs_snap_destroy(zsb); | |
187 | #endif /* HAVE_SNAPSHOT */ | |
188 | ||
189 | kill_anon_super(sb); | |
190 | } | |
191 | ||
192 | const struct super_operations zpl_super_operations = { | |
193 | .alloc_inode = zpl_inode_alloc, | |
194 | .destroy_inode = zpl_inode_destroy, | |
51f0bbe4 BB |
195 | .dirty_inode = NULL, |
196 | .write_inode = NULL, | |
197 | .drop_inode = NULL, | |
2c395def BB |
198 | #ifdef HAVE_EVICT_INODE |
199 | .evict_inode = zpl_evict_inode, | |
200 | #else | |
201 | .clear_inode = zpl_clear_inode, | |
202 | .delete_inode = zpl_inode_delete, | |
203 | #endif /* HAVE_EVICT_INODE */ | |
51f0bbe4 BB |
204 | .put_super = zpl_put_super, |
205 | .write_super = NULL, | |
03f9ba9d | 206 | .sync_fs = zpl_sync_fs, |
51f0bbe4 | 207 | .statfs = zpl_statfs, |
0de19dad | 208 | .remount_fs = zpl_remount_fs, |
51f0bbe4 BB |
209 | .show_options = zpl_show_options, |
210 | .show_stats = NULL, | |
211 | }; | |
212 | ||
213 | #if 0 | |
214 | const struct export_operations zpl_export_operations = { | |
215 | .fh_to_dentry = NULL, | |
216 | .fh_to_parent = NULL, | |
217 | .get_parent = NULL, | |
218 | }; | |
219 | #endif | |
220 | ||
221 | struct file_system_type zpl_fs_type = { | |
222 | .owner = THIS_MODULE, | |
223 | .name = ZFS_DRIVER, | |
224 | .get_sb = zpl_get_sb, | |
225 | .kill_sb = zpl_kill_sb, | |
226 | }; |