Whamcloud - gitweb
71474ddb1f7104c2a1d407a3544365fc7d678305
[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         if (!I2SMI(inode)) {
43                 struct inode *cache_inode = NULL;
44                 struct smfs_iget_args *sargs;
45                 unsigned long ino;
46
47                 sargs = (struct smfs_iget_args *)opaque;
48                 
49                 /* getting backing fs inode. */
50                 ino = sargs ? sargs->s_ino : inode->i_ino;
51                 //ino = sargs->s_ino;
52                 cache_inode = iget(S2CSB(inode->i_sb), ino); 
53                 
54                 OBD_ALLOC(inode->u.generic_ip,
55                           sizeof(struct smfs_inode_info));
56         
57                 LASSERT(inode->u.generic_ip);
58                 I2CI(inode) = cache_inode;
59         
60                 CDEBUG(D_INODE, "cache_inode %lu i_count %d\n",
61                        cache_inode->i_ino, atomic_read(&cache_inode->i_count));
62         
63                 post_smfs_inode(inode, cache_inode);
64                 sm_set_inode_ops(cache_inode, inode);
65         
66                 if (sargs) { 
67                         struct inode *dir = sargs->s_inode; 
68                         if (dir)
69                                 I2SMI(inode)->smi_flags = I2SMI(dir)->smi_flags;
70                 }
71         }
72 }
73
74 static void smfs_clear_inode_info(struct inode *inode)
75 {
76         if (I2SMI(inode)) {
77                 struct inode *cache_inode = I2CI(inode);
78
79                 CDEBUG(D_INODE, "Clear_info: cache_inode %lu\n", cache_inode->i_ino);
80
81                 LASSERTF(((atomic_read(&cache_inode->i_count) == 1) || 
82                           cache_inode == cache_inode->i_sb->s_root->d_inode),
83                          "inode %p cache inode %p #%lu i_count %d != 1 \n", 
84                          inode, cache_inode, cache_inode->i_ino, 
85                          atomic_read(&cache_inode->i_count));
86                 
87                 //if (cache_inode != cache_inode->i_sb->s_root->d_inode)
88                 iput(cache_inode);
89                 
90                 OBD_FREE(inode->u.generic_ip,
91                          sizeof(struct smfs_inode_info));
92                 inode->u.generic_ip = NULL;
93         }
94 }
95
96 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
97 static void smfs_read_inode2(struct inode *inode, void *opaque)
98 {
99         ENTRY;
100
101         if (!inode) {
102                 EXIT;
103                 return;
104         }
105         
106         CDEBUG(D_INODE, "read_inode ino %lu\n", inode->i_ino);
107         smfs_init_inode_info(inode, opaque);
108         CDEBUG(D_INODE, "read_inode ino %lu icount %d \n",
109                inode->i_ino, atomic_read(&inode->i_count));
110         EXIT;
111 }
112
113 static int smfs_test_inode(struct inode *inode, unsigned long ino, 
114                            void *opaque)
115 #else
116 static int smfs_test_inode(struct inode *inode, void *opaque)
117 #endif
118 {
119         struct smfs_iget_args *sargs = (struct smfs_iget_args*)opaque;
120
121         if (!sargs || (inode->i_ino != sargs->s_ino))
122                 return 0;
123         
124 #ifdef CONFIG_SNAPFS
125         if (SMFS_DO_COW(S2SMI(inode->i_sb)) && 
126             !smfs_snap_test_inode(inode, opaque))
127                 return 0;  
128 #endif
129         
130         return 1;
131 }
132
133 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
134 int smfs_set_inode(struct inode *inode, void *opaque)
135 {
136         //smfs_read_inode2(inode, opaque);
137         return 0;
138 }
139
140 struct inode *smfs_iget(struct super_block *sb, ino_t hash,
141                         struct smfs_iget_args *sargs)
142 {
143         struct inode *inode;
144         LASSERT(hash != 0);
145
146         inode = iget5_locked(sb, hash, smfs_test_inode,
147                              smfs_set_inode, sargs);
148         if (inode) {
149                 if (inode->i_state & I_NEW) {
150                         smfs_init_inode_info(inode, (void*)sargs);
151                         unlock_new_inode(inode);
152                 }
153                 inode->i_ino = hash;
154                 CDEBUG(D_VFSTRACE, "inode: %lu/%u(%p) index %d "
155                        "ino %d\n", inode->i_ino, inode->i_generation,
156                        inode, sargs->s_index, sargs->s_ino);
157         }
158         
159         return inode;
160 }
161 #else
162 struct inode *smfs_iget(struct super_block *sb, ino_t hash,
163                         struct smfs_iget_args *sargs)
164 {
165         struct inode *inode;
166         LASSERT(hash != 0);
167
168         inode = iget4(sb, hash, smfs_test_inode, sargs);
169         if (inode) {
170                 struct inode *cache_inode = I2CI(inode);
171                 
172                 CDEBUG(D_VFSTRACE, "new inode: %lu/%u(%p)\n", inode->i_ino,
173                        inode->i_generation, inode);
174         }
175         return inode;
176 }
177 #endif
178
179 struct inode *smfs_get_inode(struct super_block *sb, ino_t hash,
180                              struct inode *dir, int index)
181 {
182         struct smfs_iget_args sargs;
183         struct inode *inode;
184         ENTRY;
185        
186         sargs.s_ino = hash; 
187         sargs.s_inode = dir; 
188         sargs.s_index = index;
189         CDEBUG(D_VFSTRACE, "get_inode: %lu\n", hash);
190
191         inode = smfs_iget(sb, hash, &sargs);
192
193         RETURN(inode);
194 }
195  
196 static void smfs_delete_inode(struct inode *inode)
197 {
198         ENTRY;
199         clear_inode(inode);
200         EXIT;
201 }
202
203 static void smfs_write_inode(struct inode *inode, int wait)
204 {
205         struct inode *cache_inode;
206         ENTRY;
207
208         cache_inode = I2CI(inode);
209         LASSERT(cache_inode != NULL);
210         
211         CDEBUG(D_INODE,"Write inode %lu\n",inode->i_ino);
212
213         pre_smfs_inode(inode, cache_inode);
214         
215         if (cache_inode->i_sb->s_op->write_inode)
216                 cache_inode->i_sb->s_op->write_inode(cache_inode, wait);
217         
218         post_smfs_inode(inode, cache_inode);
219         EXIT;
220 }
221
222 static void smfs_dirty_inode(struct inode *inode)
223 {
224         struct inode *cache_inode;
225         ENTRY;
226
227         cache_inode = I2CI(inode);
228         if (!cache_inode || !S2CSB(inode->i_sb)) {
229                 EXIT;
230                 return;
231         }
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 static void smfs_put_inode(struct inode *inode)
241 {
242 #if 0
243         struct inode *cache_inode;
244         ENTRY;
245
246         cache_inode = I2CI(inode);
247         LASSERT(cache_inode != NULL);
248
249         if (atomic_read(&cache_inode->i_count) > 1)
250                 iput(cache_inode);
251
252         /*
253          * check if we have to release backend inode. As iput() calls fs
254          * specific ->put_inode() first and than decrements inode rerfcount, we
255          * should check here ->i_count for 1, not for 0.
256
257          * In principle we could rely on ->clear_inode(), but it will be called
258          * later, and thus we will have iputing of @inode and @cache_inode in
259          * different control paths, this is why we do it here. --umka
260          */
261         if (atomic_read(&inode->i_count) == 1 &&
262             cache_inode->i_sb->s_root->d_inode != cache_inode)
263                 smfs_clear_inode_info(inode);
264         
265         EXIT;
266 #endif
267 }
268
269 static void smfs_clear_inode(struct inode *inode)
270 {
271         ENTRY;
272         smfs_clear_inode_info(inode);
273         EXIT;
274 }
275
276 static void smfs_write_super(struct super_block *sb)
277 {
278         ENTRY;
279
280         if (!S2CSB(sb)) {
281                 EXIT;
282                 return;
283         }
284
285         if (S2CSB(sb)->s_op->write_super)
286                 S2CSB(sb)->s_op->write_super(S2CSB(sb));
287         duplicate_sb(sb, S2CSB(sb));
288         EXIT;
289 }
290
291 static void smfs_write_super_lockfs(struct super_block *sb)
292 {
293         struct super_block *cache_sb;
294         ENTRY;
295
296         cache_sb = S2CSB(sb);
297         if (!cache_sb) {
298                 EXIT;
299                 return;
300         }
301
302         if (cache_sb->s_op->write_super_lockfs)
303                 cache_sb->s_op->write_super_lockfs(cache_sb);
304
305         duplicate_sb(sb, cache_sb);
306         EXIT;
307 }
308
309 static void smfs_unlockfs(struct super_block *sb)
310 {
311         struct super_block *cache_sb;
312         ENTRY;
313
314         cache_sb = S2CSB(sb);
315         if (!cache_sb) {
316                 EXIT;
317                 return;
318         }
319
320         if (cache_sb->s_op->unlockfs)
321                 cache_sb->s_op->unlockfs(cache_sb);
322
323         duplicate_sb(sb, cache_sb);
324         EXIT;
325 }
326
327 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
328 static int smfs_statfs(struct super_block *sb, struct statfs *buf)
329 #else
330 static int smfs_statfs(struct super_block *sb, struct kstatfs *buf)
331 #endif
332 {
333         struct super_block *cache_sb;
334         int rc = 0;
335         ENTRY;
336
337         cache_sb = S2CSB(sb);
338         if (!cache_sb)
339                 RETURN(-EINVAL);
340
341         if (cache_sb->s_op->statfs)
342                 rc = cache_sb->s_op->statfs(cache_sb, buf);
343
344         duplicate_sb(sb, cache_sb);
345         RETURN(rc);
346 }
347 static int smfs_remount(struct super_block *sb, int *flags, char *data)
348 {
349         struct super_block *cache_sb;
350         int rc = 0;
351         ENTRY;
352
353         cache_sb = S2CSB(sb);
354
355         if (!cache_sb)
356                 RETURN(-EINVAL);
357
358         if (cache_sb->s_op->remount_fs)
359                 rc = cache_sb->s_op->remount_fs(cache_sb, flags, data);
360
361         duplicate_sb(sb, cache_sb);
362         RETURN(rc);
363 }
364
365 struct super_operations smfs_super_ops = {
366 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
367         .read_inode2        = smfs_read_inode2,
368 #endif 
369         .clear_inode        = smfs_clear_inode,
370         .put_super          = smfs_put_super,
371         .delete_inode       = smfs_delete_inode,
372         .write_inode        = smfs_write_inode,
373         .dirty_inode        = smfs_dirty_inode, /* BKL not held. */
374         .put_inode          = smfs_put_inode,   /* BKL not held. */
375         .write_super        = smfs_write_super, /* BKL held */
376         .write_super_lockfs = smfs_write_super_lockfs, /* BKL not held. */
377         .unlockfs           = smfs_unlockfs,    /* BKL not held. */
378         .statfs             = smfs_statfs,      /* BKL held */
379         .remount_fs         = smfs_remount,     /* BKL held */
380 };
381
382 int is_smfs_sb(struct super_block *sb)
383 {
384         return (sb->s_op->put_super == smfs_super_ops.put_super);
385 }
386 EXPORT_SYMBOL(is_smfs_sb);