]>
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 | { |
b3129792 | 76 | truncate_setsize(ip, 0); |
2c395def BB |
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 | { | |
b3129792 | 92 | truncate_setsize(ip, 0); |
2c395def BB |
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 | { | |
0d3ac5e7 | 110 | cred_t *cr = CRED(); |
03f9ba9d BB |
111 | int error; |
112 | ||
0d3ac5e7 | 113 | crhold(cr); |
03f9ba9d | 114 | error = -zfs_sync(sb, wait, cr); |
0d3ac5e7 | 115 | crfree(cr); |
03f9ba9d BB |
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 | ||
2cf7f52b | 153 | seq_printf(seq, ",%s", zsb->z_flags & ZSB_XATTR ? "xattr" : "noxattr"); |
51f0bbe4 BB |
154 | |
155 | return (0); | |
156 | } | |
157 | ||
158 | static int | |
159 | zpl_fill_super(struct super_block *sb, void *data, int silent) | |
160 | { | |
161 | int error; | |
162 | ||
163 | error = -zfs_domount(sb, data, silent); | |
164 | ASSERT3S(error, <=, 0); | |
165 | ||
166 | return (error); | |
167 | } | |
168 | ||
2cf7f52b BB |
169 | #ifdef HAVE_MOUNT_NODEV |
170 | static struct dentry * | |
171 | zpl_mount(struct file_system_type *fs_type, int flags, | |
172 | const char *osname, void *data) | |
173 | { | |
174 | zpl_mount_data_t zmd = { osname, data }; | |
175 | ||
176 | return mount_nodev(fs_type, flags, &zmd, zpl_fill_super); | |
177 | } | |
178 | #else | |
51f0bbe4 BB |
179 | static int |
180 | zpl_get_sb(struct file_system_type *fs_type, int flags, | |
181 | const char *osname, void *data, struct vfsmount *mnt) | |
182 | { | |
2cf7f52b | 183 | zpl_mount_data_t zmd = { osname, data }; |
51f0bbe4 BB |
184 | |
185 | return get_sb_nodev(fs_type, flags, &zmd, zpl_fill_super, mnt); | |
186 | } | |
2cf7f52b | 187 | #endif /* HAVE_MOUNT_NODEV */ |
51f0bbe4 BB |
188 | |
189 | static void | |
190 | zpl_kill_sb(struct super_block *sb) | |
191 | { | |
192 | #ifdef HAVE_SNAPSHOT | |
193 | zfs_sb_t *zsb = sb->s_fs_info; | |
194 | ||
195 | if (zsb && dmu_objset_is_snapshot(zsb->z_os)) | |
196 | zfs_snap_destroy(zsb); | |
197 | #endif /* HAVE_SNAPSHOT */ | |
198 | ||
199 | kill_anon_super(sb); | |
200 | } | |
201 | ||
ab26409d BB |
202 | #ifdef HAVE_SHRINK |
203 | /* | |
204 | * Linux 3.1 - 3.x API | |
205 | * | |
206 | * The Linux 3.1 API introduced per-sb cache shrinkers to replace the | |
207 | * global ones. This allows us a mechanism to cleanly target a specific | |
208 | * zfs file system when the dnode and inode caches grow too large. | |
209 | * | |
210 | * In addition, the 3.0 kernel added the iterate_supers_type() helper | |
211 | * function which is used to safely walk all of the zfs file systems. | |
212 | */ | |
213 | static void | |
214 | zpl_prune_sb(struct super_block *sb, void *arg) | |
215 | { | |
216 | int objects = 0; | |
217 | int error; | |
218 | ||
219 | error = -zfs_sb_prune(sb, *(unsigned long *)arg, &objects); | |
220 | ASSERT3S(error, <=, 0); | |
221 | ||
222 | return; | |
223 | } | |
224 | ||
225 | void | |
226 | zpl_prune_sbs(int64_t bytes_to_scan, void *private) | |
227 | { | |
228 | unsigned long nr_to_scan = (bytes_to_scan / sizeof(znode_t)); | |
229 | ||
230 | iterate_supers_type(&zpl_fs_type, zpl_prune_sb, &nr_to_scan); | |
231 | kmem_reap(); | |
232 | } | |
233 | #else | |
234 | /* | |
235 | * Linux 2.6.x - 3.0 API | |
236 | * | |
237 | * These are best effort interfaces are provided by the SPL to induce | |
238 | * the Linux VM subsystem to reclaim a fraction of the both dnode and | |
239 | * inode caches. Ideally, we want to just target the zfs file systems | |
240 | * however our only option is to reclaim from them all. | |
241 | */ | |
242 | void | |
243 | zpl_prune_sbs(int64_t bytes_to_scan, void *private) | |
244 | { | |
245 | unsigned long nr_to_scan = (bytes_to_scan / sizeof(znode_t)); | |
246 | ||
247 | shrink_dcache_memory(nr_to_scan, GFP_KERNEL); | |
248 | shrink_icache_memory(nr_to_scan, GFP_KERNEL); | |
249 | kmem_reap(); | |
250 | } | |
251 | #endif /* HAVE_SHRINK */ | |
252 | ||
253 | #ifdef HAVE_NR_CACHED_OBJECTS | |
254 | static int | |
255 | zpl_nr_cached_objects(struct super_block *sb) | |
256 | { | |
257 | zfs_sb_t *zsb = sb->s_fs_info; | |
258 | int nr; | |
259 | ||
260 | mutex_enter(&zsb->z_znodes_lock); | |
261 | nr = zsb->z_nr_znodes; | |
262 | mutex_exit(&zsb->z_znodes_lock); | |
263 | ||
264 | return (nr); | |
265 | } | |
266 | #endif /* HAVE_NR_CACHED_OBJECTS */ | |
267 | ||
268 | #ifdef HAVE_FREE_CACHED_OBJECTS | |
269 | /* | |
270 | * Attempt to evict some meta data from the cache. The ARC operates in | |
271 | * terms of bytes while the Linux VFS uses objects. Now because this is | |
272 | * just a best effort eviction and the exact values aren't critical so we | |
273 | * extrapolate from an object count to a byte size using the znode_t size. | |
274 | */ | |
275 | static void | |
276 | zpl_free_cached_objects(struct super_block *sb, int nr_to_scan) | |
277 | { | |
278 | arc_adjust_meta(nr_to_scan * sizeof(znode_t), B_FALSE); | |
279 | } | |
280 | #endif /* HAVE_FREE_CACHED_OBJECTS */ | |
281 | ||
51f0bbe4 | 282 | const struct super_operations zpl_super_operations = { |
ab26409d BB |
283 | .alloc_inode = zpl_inode_alloc, |
284 | .destroy_inode = zpl_inode_destroy, | |
285 | .dirty_inode = NULL, | |
286 | .write_inode = NULL, | |
287 | .drop_inode = NULL, | |
2c395def | 288 | #ifdef HAVE_EVICT_INODE |
ab26409d | 289 | .evict_inode = zpl_evict_inode, |
2c395def | 290 | #else |
ab26409d BB |
291 | .clear_inode = zpl_clear_inode, |
292 | .delete_inode = zpl_inode_delete, | |
2c395def | 293 | #endif /* HAVE_EVICT_INODE */ |
ab26409d BB |
294 | .put_super = zpl_put_super, |
295 | .write_super = NULL, | |
296 | .sync_fs = zpl_sync_fs, | |
297 | .statfs = zpl_statfs, | |
298 | .remount_fs = zpl_remount_fs, | |
299 | .show_options = zpl_show_options, | |
300 | .show_stats = NULL, | |
301 | #ifdef HAVE_NR_CACHED_OBJECTS | |
302 | .nr_cached_objects = zpl_nr_cached_objects, | |
303 | #endif /* HAVE_NR_CACHED_OBJECTS */ | |
304 | #ifdef HAVE_FREE_CACHED_OBJECTS | |
305 | .free_cached_objects = zpl_free_cached_objects, | |
306 | #endif /* HAVE_FREE_CACHED_OBJECTS */ | |
51f0bbe4 BB |
307 | }; |
308 | ||
51f0bbe4 | 309 | struct file_system_type zpl_fs_type = { |
ab26409d BB |
310 | .owner = THIS_MODULE, |
311 | .name = ZFS_DRIVER, | |
2cf7f52b | 312 | #ifdef HAVE_MOUNT_NODEV |
ab26409d | 313 | .mount = zpl_mount, |
2cf7f52b | 314 | #else |
ab26409d | 315 | .get_sb = zpl_get_sb, |
2cf7f52b | 316 | #endif /* HAVE_MOUNT_NODEV */ |
ab26409d | 317 | .kill_sb = zpl_kill_sb, |
51f0bbe4 | 318 | }; |