/[dazuko]/dazuko/nullfs/dentry.c
ViewVC logotype

Contents of /dazuko/nullfs/dentry.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (show annotations) (download)
Thu Jul 10 18:32:46 2008 UTC (15 years, 4 months ago) by ogman
Branch: MAIN
Changes since 1.1: +164 -0 lines
File MIME type: text/plain
- add kerneldoc
- review

1 /* nullfs: pass-through stackable filesystem
2
3 Copyright (C) 1997-2003 Erez Zadok
4 Copyright (C) 2001-2003 Stony Brook University
5 Copyright (C) 2004-2006 International Business Machines Corp.
6 Copyright (C) 2008 John Ogness
7 Author: John Ogness <dazukocode@ogness.net>
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24 #include <linux/module.h>
25 #include <linux/fs.h>
26 #include <linux/namei.h>
27 #include <linux/mount.h>
28 #include <linux/fs_stack.h>
29 #include "nullfs_fs.h"
30
31 extern struct kmem_cache *nullfs_dentry_info_cachep;
32
33 /**
34 * nullfs_d_revalidate - revalidate a dentry found in the dcache
35 * @dentry: dentry to revalidate
36 * @nd: nameidata associated with dentry
37 *
38 * Description: Called when the VFS needs to revalidate a dentry. This is
39 * called whenever a name look-up finds a dentry in the dcache. Most
40 * filesystems leave this as NULL, because all their dentries in the dcache
41 * are valid.
42 *
43 * Call d_revalidate() on the lower dentry if available. The mnt/dentry
44 * (path) data in the nameidata needs to be temporarily swapped out for the
45 * lower call.
46 *
47 * After the call, the original path data is restored and the dentry's inode
48 * attributes are updated to match the lower inode.
49 *
50 * Returns 1 if dentry is valid, otherwise 0.
51 */
52 static int nullfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
53 {
54 struct vfsmount *lower_mnt;
55 struct dentry *lower_dentry;
56 struct vfsmount *vfsmount_save;
57 struct dentry *dentry_save;
58 int valid;
59
60 valid = 1;
61
62 lower_dentry = GET_LOWER_DENTRY(dentry);
63
64 if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate)
65 goto out;
66
67 lower_mnt = GET_LOWER_MNT(dentry);
68
69 vfsmount_save = nd->path.mnt;
70 dentry_save = nd->path.dentry;
71
72 nd->path.mnt = mntget(lower_mnt);
73 nd->path.dentry = dget(lower_dentry);
74
75 valid = lower_dentry->d_op->d_revalidate(lower_dentry, nd);
76
77 mntput(lower_mnt);
78 dput(lower_dentry);
79
80 nd->path.mnt = vfsmount_save;
81 nd->path.dentry = dentry_save;
82
83 /* XXX: What do we do if (valid != 1) ? */
84
85 if (dentry->d_inode) {
86 struct inode *lower_inode;
87
88 lower_inode = GET_LOWER_INODE(dentry->d_inode);
89
90 fsstack_copy_attr_all(dentry->d_inode, lower_inode, NULL);
91 }
92 out:
93 return valid;
94 }
95
96 /**
97 * nullfs_d_hash - hash the given name
98 * @dentry: the parent dentry
99 * @name: the name to hash
100 *
101 * Description: Called when the VFS adds a dentry to the hash table.
102 *
103 * Call d_hash() on the lower dentry if available.
104 *
105 * Returns 0 on success.
106 */
107 static int nullfs_d_hash(struct dentry *dentry, struct qstr *name)
108 {
109 struct dentry *lower_dentry = GET_LOWER_DENTRY(dentry);
110
111 if (!lower_dentry || !lower_dentry->d_op ||
112 !lower_dentry->d_op->d_hash) {
113 return 0;
114 }
115
116 return lower_dentry->d_op->d_hash(lower_dentry, name);
117 }
118
119 /**
120 * nullfs_d_release - clean up dentry
121 * @dentry: the dentry that will be released
122 *
123 * Description: Called when a dentry is really deallocated.
124 *
125 * Release our hold on the lower dentry and mnt. Then free the structure
126 * (from the cache) containing the lower data for this dentry.
127 */
128 static void nullfs_d_release(struct dentry *dentry)
129 {
130 if (GET_DENTRY_INFO(dentry)) {
131 dput(GET_LOWER_DENTRY(dentry));
132 mntput(GET_LOWER_MNT(dentry));
133
134 kmem_cache_free(nullfs_dentry_info_cachep,
135 GET_DENTRY_INFO(dentry));
136 }
137 }
138
139 /**
140 * nullfs_d_compare - used to compare dentry's
141 * @dentry: the parent dentry
142 * @a: qstr of an existing dentry
143 * @b: qstr of a second dentry (dentry may not be valid)
144 *
145 * Description: Called when a dentry should be compared with another.
146 *
147 * Call d_compare() on the lower dentry if available. Otherwise, perform
148 * some basic comparisons between the two qstr's.
149 *
150 * Returns 0 if they are the same, otherwise 1.
151 */
152 static int nullfs_d_compare(struct dentry *dentry, struct qstr *a,
153 struct qstr *b)
154 {
155 struct dentry *lower_dentry = GET_LOWER_DENTRY(dentry);
156
157 if (lower_dentry && lower_dentry->d_op &&
158 lower_dentry->d_op->d_compare) {
159
160 return lower_dentry->d_op->d_compare(lower_dentry, a, b);
161 }
162
163 if (a->len != b->len)
164 return 1;
165 if (memcmp(a->name, b->name, a->len))
166 return 1;
167
168 return 0;
169
170 }
171
172 #ifdef NULLFS_HOOK_UNNEEDED
173 /**
174 * nullfs_d_delete - called when refcount is 0
175 * @dentry: dentry to delete
176 *
177 * Description: Called when the last reference to a dentry is deleted.
178 * This means no-one is using the dentry, however it is still valid and
179 * in the dcache.
180 *
181 * nullfs does not need to do anything here. When the last reference to
182 * a lower dentry is deleted, the VFS subsystem will call this function
183 * directly on the lower dentry.
184 *
185 * Returns 0 on success.
186 */
187 static int nullfs_d_delete(struct dentry *dentry)
188 {
189 return 0;
190 }
191
192 /**
193 * nullfs_d_iput - called when dentry loses its inode
194 * @dentry: dentry that loses the inode
195 * @inode: the inode being lost
196 *
197 * Description: Called when a dentry loses its inode (just prior to its
198 * being deallocated). The default when this is NULL is that the VFS calls
199 * iput(). If you define this method, you must call iput() yourself.
200 *
201 * nullfs does not need to do anything with the lower dentry here. When
202 * the lower dentry loses its inode, the VFS subsystem will call this
203 * function directy on the lower dentry.
204 */
205 static void nullfs_d_iput(struct dentry *dentry, struct inode *inode)
206 {
207 iput(inode);
208 }
209 #endif /* NULLFS_HOOK_UNNEEDED */
210
211 #ifdef NULLFS_HOOK_UNWANTED
212 /**
213 * nullfs_d_dname: dynamically create a name for the dentry
214 * @dentry: the dentry to create a name for
215 * @buffer: buffer to hold the name
216 * @buflen: size of the buffer
217 *
218 * Description: Called when the pathname of a dentry should be generated.
219 * Usefull for some pseudo filesystems (sockfs, pipefs, ...) to delay
220 * pathname generation. (Instead of doing it when dentry is created, its
221 * done only when the path is needed.). Real filesystems probably don't
222 * want to use it, because their dentries are present in global dcache
223 * hash, so their hash should be an invariant. As no lock is held,
224 * d_dname() should not try to modify the dentry itself, unless
225 * appropriate SMP safety is used. CAUTION : d_path() logic is quite tricky.
226 * The correct way to return for example "Hello" is to put it at the end of
227 * the buffer, and returns a pointer to the first char. dynamic_dname()
228 * helper function is provided to take care of this.
229 *
230 * Call d_name() on the lower dentry if available. Otherwise, handle this
231 * the way that pipefs does it.
232 *
233 * WARNING: If this hook is enabled, _ALL_ dpath() lookups will result
234 * in this function being called instead of doing a real file
235 * name lookup.
236 *
237 * Returns a dynamically created name (as a pointer within the buffer).
238 */
239 static char * nullfs_d_dname(struct dentry *dentry, char *buffer, int buflen)
240 {
241 struct dentry *lower_dentry = GET_LOWER_DENTRY(dentry);
242
243 if (lower_dentry && lower_dentry->d_op &&
244 lower_dentry->d_op->d_dname) {
245
246 return lower_dentry->d_op->d_dname(dentry, buffer, buflen);
247 }
248
249 return dynamic_dname(dentry, buffer, buflen, "nullfs:[%lu]",
250 dentry->d_inode->i_ino);
251 }
252 #endif /* NULLFS_HOOK_UNWANTED */
253
254 struct dentry_operations nullfs_dops = {
255 .d_revalidate = nullfs_d_revalidate,
256 .d_hash = nullfs_d_hash,
257 .d_release = nullfs_d_release,
258 .d_compare = nullfs_d_compare,
259 #ifdef NULLFS_HOOK_UNNEEDED
260 .d_delete = nullfs_d_delete,
261 .d_iput = nullfs_d_iput,
262 #endif
263 #ifdef NULLFS_HOOK_UNWANTED
264 .d_dname = nullfs_d_dname,
265 #endif
266 };
267

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26