]>
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 | ||
132 | static int | |
133 | zpl_show_options(struct seq_file *seq, struct vfsmount *vfsp) | |
134 | { | |
135 | struct super_block *sb = vfsp->mnt_sb; | |
136 | zfs_sb_t *zsb = sb->s_fs_info; | |
137 | ||
138 | /* | |
139 | * The Linux VFS automatically handles the following flags: | |
140 | * MNT_NOSUID, MNT_NODEV, MNT_NOEXEC, MNT_NOATIME, MNT_READONLY | |
141 | */ | |
142 | ||
143 | if (zsb->z_flags & ZSB_XATTR_USER) | |
144 | seq_printf(seq, ",%s", "xattr"); | |
145 | ||
146 | return (0); | |
147 | } | |
148 | ||
149 | static int | |
150 | zpl_fill_super(struct super_block *sb, void *data, int silent) | |
151 | { | |
152 | int error; | |
153 | ||
154 | error = -zfs_domount(sb, data, silent); | |
155 | ASSERT3S(error, <=, 0); | |
156 | ||
157 | return (error); | |
158 | } | |
159 | ||
160 | static int | |
161 | zpl_get_sb(struct file_system_type *fs_type, int flags, | |
162 | const char *osname, void *data, struct vfsmount *mnt) | |
163 | { | |
164 | zpl_mount_data_t zmd = { osname, data, mnt }; | |
165 | ||
166 | return get_sb_nodev(fs_type, flags, &zmd, zpl_fill_super, mnt); | |
167 | } | |
168 | ||
169 | static void | |
170 | zpl_kill_sb(struct super_block *sb) | |
171 | { | |
172 | #ifdef HAVE_SNAPSHOT | |
173 | zfs_sb_t *zsb = sb->s_fs_info; | |
174 | ||
175 | if (zsb && dmu_objset_is_snapshot(zsb->z_os)) | |
176 | zfs_snap_destroy(zsb); | |
177 | #endif /* HAVE_SNAPSHOT */ | |
178 | ||
179 | kill_anon_super(sb); | |
180 | } | |
181 | ||
182 | const struct super_operations zpl_super_operations = { | |
183 | .alloc_inode = zpl_inode_alloc, | |
184 | .destroy_inode = zpl_inode_destroy, | |
51f0bbe4 BB |
185 | .dirty_inode = NULL, |
186 | .write_inode = NULL, | |
187 | .drop_inode = NULL, | |
2c395def BB |
188 | #ifdef HAVE_EVICT_INODE |
189 | .evict_inode = zpl_evict_inode, | |
190 | #else | |
191 | .clear_inode = zpl_clear_inode, | |
192 | .delete_inode = zpl_inode_delete, | |
193 | #endif /* HAVE_EVICT_INODE */ | |
51f0bbe4 BB |
194 | .put_super = zpl_put_super, |
195 | .write_super = NULL, | |
03f9ba9d | 196 | .sync_fs = zpl_sync_fs, |
51f0bbe4 BB |
197 | .freeze_fs = NULL, |
198 | .unfreeze_fs = NULL, | |
199 | .statfs = zpl_statfs, | |
200 | .remount_fs = NULL, | |
201 | .show_options = zpl_show_options, | |
202 | .show_stats = NULL, | |
203 | }; | |
204 | ||
205 | #if 0 | |
206 | const struct export_operations zpl_export_operations = { | |
207 | .fh_to_dentry = NULL, | |
208 | .fh_to_parent = NULL, | |
209 | .get_parent = NULL, | |
210 | }; | |
211 | #endif | |
212 | ||
213 | struct file_system_type zpl_fs_type = { | |
214 | .owner = THIS_MODULE, | |
215 | .name = ZFS_DRIVER, | |
216 | .get_sb = zpl_get_sb, | |
217 | .kill_sb = zpl_kill_sb, | |
218 | }; |