Whamcloud - gitweb
- fixed stupid bug with locking in MDS. It caused clients do not flush local
[fs/lustre-release.git] / lustre / smfs / inode.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  lustre/smfs/inode.c
5  *  Lustre filesystem abstraction routines
6  *
7  *  Copyright (C) 2004 Cluster File Systems, Inc.
8  *
9  *   This file is part of Lustre, http://www.lustre.org.
10  *
11  *   Lustre is free software; you can redistribute it and/or
12  *   modify it under the terms of version 2 of the GNU General Public
13  *   License as published by the Free Software Foundation.
14  *
15  *   Lustre is distributed in the hope that it will be useful,
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *   GNU General Public License for more details.
19  *
20  *   You should have received a copy of the GNU General Public License
21  *   along with Lustre; if not, write to the Free Software
22  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25 #define DEBUG_SUBSYSTEM S_SM
26
27 #include <linux/kmod.h>
28 #include <linux/init.h>
29 #include <linux/fs.h>
30 #include <linux/slab.h>
31 #include <linux/string.h>
32 #include <linux/obd_class.h>
33 #include <linux/obd_support.h>
34 #include <linux/lustre_lib.h>
35 #include <linux/lustre_idl.h>
36 #include <linux/lustre_fsfilt.h>
37 #include <linux/lustre_smfs.h>
38 #include "smfs_internal.h"
39
40 static void smfs_init_inode_info (struct inode *inode, void *opaque)
41 {
42         struct smfs_iget_args *sargs = (struct smfs_iget_args*)opaque;
43         struct inode *cache_inode = NULL;
44         
45         if (sargs)
46                 cache_inode = iget(S2CSB(inode->i_sb), sargs->s_ino);
47         else 
48                 cache_inode = iget(S2CSB(inode->i_sb), inode->i_ino); 
49                  
50         OBD_ALLOC(I2SMI(inode), sizeof(struct smfs_inode_info));
51         LASSERT(I2SMI(inode));
52         I2CI(inode) = cache_inode;
53         CDEBUG(D_INODE, "cache_inode i_count ino %lu i_count %d\n",
54                cache_inode->i_ino, atomic_read(&cache_inode->i_count));
55         post_smfs_inode(inode, cache_inode);
56         sm_set_inode_ops(cache_inode, inode);
57         if (sargs) { 
58                 struct inode *dir = sargs->s_inode; 
59                 if (dir)
60                         I2SMI(inode)->smi_flags = I2SMI(dir)->smi_flags;
61         }
62 }
63
64 static void smfs_clear_inode_info(struct inode *inode)
65 {
66         if (I2SMI(inode)) {
67                 struct inode *cache_inode = I2CI(inode);
68                 LASSERTF(((atomic_read(&cache_inode->i_count) == 1) || 
69                            cache_inode == cache_inode->i_sb->s_root->d_inode),  
70                          "inode %p cache inode %p %lu i_count %d != 0 \n", 
71                           inode, cache_inode, cache_inode->i_ino, 
72                           atomic_read(&cache_inode->i_count));
73                 if (cache_inode != cache_inode->i_sb->s_root->d_inode)
74                         iput(cache_inode);
75                 OBD_FREE(I2SMI(inode), sizeof(struct smfs_inode_info));
76                 I2SMI(inode) = NULL;
77         }
78 }
79
80 static void smfs_read_inode2(struct inode *inode, void *opaque)
81 {
82         ENTRY;
83
84         if (!inode)
85                 return;
86         
87         CDEBUG(D_INODE, "read_inode ino %lu\n", inode->i_ino);
88         smfs_init_inode_info(inode, opaque);
89         CDEBUG(D_INODE, "read_inode ino %lu icount %d \n",
90                inode->i_ino, atomic_read(&inode->i_count));
91         EXIT;
92         return;
93 }
94
95 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
96 static int smfs_test_inode(struct inode *inode, unsigned long ino, 
97                                   void *opaque)
98 #else
99 static int smfs_test_inode(struct inode *inode, void *opaque)
100 #endif
101 {
102         struct smfs_iget_args *sargs = (struct smfs_iget_args*)opaque;
103
104         LASSERT(sargs);
105         if (!sargs)
106                 return 1;
107
108         if (inode->i_ino != sargs->s_ino)
109                 return 0; 
110 #ifdef CONFIG_SNAPFS        
111         if (SMFS_DO_COW(S2SMI(inode->i_sb)) && 
112             !smfs_snap_test_inode(inode, opaque))
113                 return 0;  
114 #endif  
115         if (I2SMI(inode)) {
116                 struct inode *cache_inode = I2CI(inode);
117         
118                 LASSERTF(cache_inode->i_ino == inode->i_ino, 
119                          "inode ino %lu != cache ino %lu",
120                          cache_inode->i_ino, inode->i_ino); 
121         }
122         if (!I2SMI(inode))
123                 smfs_init_inode_info(inode, opaque); 
124         return 1;
125 }
126
127 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
128 int smfs_set_inode(struct inode *inode, void *opaque)
129 {
130         smfs_read_inode2(inode, opaque);
131         return 0;
132 }
133
134 struct inode *smfs_iget(struct super_block *sb, ino_t hash,
135                         struct smfs_iget_args *sargs)
136 {
137         struct inode *inode;
138
139         LASSERT(hash != 0);
140
141         inode = iget5_locked(sb, hash, smfs_test_inode, smfs_set_inode, sargs);
142         if (inode) {
143                 if (inode->i_state & I_NEW)
144                         unlock_new_inode(inode);
145                 CDEBUG(D_VFSTRACE, "inode: %lu/%u(%p) index %d ino %lu \n", 
146                        inode->i_ino, inode->i_generation, inode, sargs->s_index, 
147                        sargs->s_ino);
148                 inode->i_ino = hash;
149         }
150         return inode;
151 }
152 #else
153 struct inode *smfs_iget(struct super_block *sb, ino_t hash,
154                         struct smfs_iget_args *sargs)
155 {
156         struct inode *inode;
157         LASSERT(hash != 0);
158
159         inode = iget4(sb, hash, smfs_test_inode, sargs);
160
161         if (inode) {
162                 struct inode *cache_inode = I2CI(inode);
163
164                 LASSERTF((inode->i_ino == cache_inode->i_ino), 
165                          "inode %p ino %lu != cache inode %p ino %lu",
166                           inode, inode->i_ino, cache_inode, cache_inode->i_ino); 
167                 CDEBUG(D_VFSTRACE, "inode: %lu/%u(%p)\n", inode->i_ino,
168                        inode->i_generation, inode);
169         }
170         return inode;
171 }
172 #endif
173 struct inode *smfs_get_inode (struct super_block *sb, ino_t hash,
174                               struct inode *dir, int index)
175 {
176         struct inode *inode;
177         struct smfs_iget_args sargs; 
178         ENTRY;
179        
180         sargs.s_index = index;
181         sargs.s_inode = dir; 
182         sargs.s_ino = hash; 
183         inode = smfs_iget(sb, hash, &sargs);
184         
185         RETURN(inode);
186 }
187  
188 static void smfs_delete_inode(struct inode *inode)
189 {
190         struct inode *cache_inode;
191
192         ENTRY;
193         if (I2SMI(inode)) {
194                 cache_inode = I2CI(inode);
195                 if (!cache_inode || !S2CSB(inode->i_sb))
196                         return;
197                 post_smfs_inode(inode, cache_inode);
198                 smfs_clear_inode_info(inode);
199         }
200         inode->i_state = I_CLEAR;
201         return;
202 }
203
204 static void smfs_write_inode(struct inode *inode, int wait)
205 {
206         struct inode *cache_inode;
207
208         ENTRY;
209         cache_inode = I2CI(inode);
210
211         if (!cache_inode) {
212                 CWARN("cache inode null\n");
213                 return;
214         }
215         pre_smfs_inode(inode, cache_inode);
216         if (S2CSB(inode->i_sb)->s_op->write_inode)
217                 S2CSB(inode->i_sb)->s_op->write_inode(cache_inode, wait);
218         
219         post_smfs_inode(inode, cache_inode);
220         EXIT;
221 }
222
223 static void smfs_dirty_inode(struct inode *inode)
224 {
225         struct inode *cache_inode;
226
227         ENTRY;
228         cache_inode = I2CI(inode);
229
230         if (!cache_inode || !S2CSB(inode->i_sb))
231                 return;
232
233         pre_smfs_inode(inode, cache_inode);
234         if (S2CSB(inode->i_sb)->s_op->dirty_inode)
235                 S2CSB(inode->i_sb)->s_op->dirty_inode(cache_inode);
236
237         post_smfs_inode(inode, cache_inode);
238         EXIT;
239 }
240
241 static void smfs_put_inode(struct inode *inode)
242 {
243         struct inode *cache_inode;
244
245         ENTRY;
246         cache_inode = I2CI(inode);
247
248         if (!cache_inode) {
249                 CWARN("cache inode null\n");
250                 return;
251         }
252         
253         if (atomic_read(&cache_inode->i_count) > 1) {
254                 iput(cache_inode);
255         }
256         
257         if (S2CSB(inode->i_sb)->s_op->put_inode)
258                 S2CSB(inode->i_sb)->s_op->put_inode(cache_inode);
259         
260         if (atomic_read(&inode->i_count) == 0 &&
261             cache_inode->i_sb->s_root->d_inode != cache_inode)
262                 smfs_clear_inode_info(inode);
263         
264         EXIT;
265 }
266
267 static void smfs_write_super(struct super_block *sb)
268 {
269         ENTRY;
270
271         if (!S2CSB(sb))
272                 return;
273
274         if (S2CSB(sb)->s_op->write_super)
275                 S2CSB(sb)->s_op->write_super(S2CSB(sb));
276         duplicate_sb(sb, S2CSB(sb));
277         EXIT;
278         return;
279 }
280
281 static void smfs_clear_inode(struct inode *inode)
282 {
283         struct inode *cache_inode;
284         
285         ENTRY;
286
287         if (!inode) return;
288         
289         cache_inode = I2CI(inode);
290
291         smfs_clear_inode_info(inode);
292         
293         EXIT;
294         return;
295 }
296
297 static void smfs_write_super_lockfs(struct super_block *sb)
298 {
299         struct super_block *cache_sb;
300         ENTRY;
301
302         cache_sb = S2CSB(sb);
303         if (!cache_sb)
304                 return;
305
306         if (cache_sb->s_op->write_super_lockfs)
307                 cache_sb->s_op->write_super_lockfs(cache_sb);
308
309         duplicate_sb(sb, cache_sb);
310         EXIT;
311 }
312
313 static void smfs_unlockfs(struct super_block *sb)
314 {
315         struct super_block *cache_sb;
316         ENTRY;
317
318         cache_sb = S2CSB(sb);
319         if (!cache_sb)
320                 return;
321
322         if (cache_sb->s_op->unlockfs)
323                 cache_sb->s_op->unlockfs(cache_sb);
324
325         duplicate_sb(sb, cache_sb);
326         EXIT;
327 }
328
329 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
330 static int smfs_statfs(struct super_block *sb, struct statfs *buf)
331 #else
332 static int smfs_statfs(struct super_block *sb, struct kstatfs *buf)
333 #endif
334 {
335         struct super_block *cache_sb;
336         int rc = 0;
337         ENTRY;
338
339         cache_sb = S2CSB(sb);
340         if (!cache_sb)
341                 RETURN(-EINVAL);
342
343         if (cache_sb->s_op->statfs)
344                 rc = cache_sb->s_op->statfs(cache_sb, buf);
345
346         duplicate_sb(sb, cache_sb);
347
348         RETURN(rc);
349 }
350 static int smfs_remount(struct super_block *sb, int *flags, char *data)
351 {
352         struct super_block *cache_sb;
353         int rc = 0;
354         ENTRY;
355
356         cache_sb = S2CSB(sb);
357
358         if (!cache_sb)
359                 RETURN(-EINVAL);
360
361         if (cache_sb->s_op->remount_fs)
362                 rc = cache_sb->s_op->remount_fs(cache_sb, flags, data);
363
364         duplicate_sb(sb, cache_sb);
365         RETURN(rc);
366 }
367 struct super_operations smfs_super_ops = {
368 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
369         .read_inode2        = smfs_read_inode2,
370 #endif 
371         .clear_inode        = smfs_clear_inode,
372         .put_super          = smfs_put_super,
373         .delete_inode       = smfs_delete_inode,
374         .write_inode        = smfs_write_inode,
375         .dirty_inode        = smfs_dirty_inode, /* BKL not held. */
376         .put_inode          = smfs_put_inode,   /* BKL not held. */
377         .write_super        = smfs_write_super, /* BKL held */
378         .write_super_lockfs = smfs_write_super_lockfs, /* BKL not held. */
379         .unlockfs           = smfs_unlockfs,    /* BKL not held. */
380         .statfs             = smfs_statfs,      /* BKL held */
381         .remount_fs         = smfs_remount,     /* BKL held */
382 };
383
384 int is_smfs_sb(struct super_block *sb)
385 {
386         return (sb->s_op->put_super == smfs_super_ops.put_super);
387 }
388 EXPORT_SYMBOL(is_smfs_sb);