Whamcloud - gitweb
5b611fbebcbad3cd7eb29f854c405fda5c913d78
[fs/lustre-release.git] / lustre / smfs / smfs_cow.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2004 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  */
22
23 #define DEBUG_SUBSYSTEM S_SM
24
25 #include <linux/module.h>
26 #include <linux/kernel.h>
27 #include <linux/string.h>
28 #include <linux/slab.h>
29 #include <linux/stat.h>
30 #include <linux/unistd.h>
31 #include <linux/smp_lock.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
38 #include <linux/lustre_snap.h>
39 #include <linux/lustre_smfs.h>
40
41 #include "smfs_internal.h"
42 #define SNAPTABLE_SIZE(size) (sizeof(struct snap_table) + size * sizeof(struct snap)) 
43 static int smfs_init_snaptabe(struct super_block *sb)
44 {
45         struct snap_info         *snap_info = S2SNAPI(sb);      
46         struct fsfilt_operations *snapops;
47         int                      rc = 0, size, table_size, vallen;
48         
49         ENTRY;
50
51         init_MUTEX(&snap_info->sntbl_sema);
52         /*Initialized table */
53         /*get the maxsize of snaptable*/
54         vallen = sizeof(int);
55         rc = snapops->fs_get_snap_info(sb, NULL, MAX_SNAPTABLE_COUNT,
56                                        strlen(MAX_SNAPTABLE_COUNT), &size, 
57                                        &vallen);
58         if (size == 0) {
59                 CERROR("the Max snaptable count should not be zero\n");
60                 RETURN(-EINVAL);
61         }
62         
63         table_size = SNAPTABLE_SIZE(size);
64
65         OBD_ALLOC(snap_info->sntbl, table_size);
66
67         if (!snap_info->sntbl) {
68                 CERROR("No MEM\n");
69                 RETURN(-ENOMEM);
70         }
71         /*get snaptable info*/
72         rc = snapops->fs_get_snap_info(sb, NULL, SNAPTABLE_INFO, 
73                                        strlen(SNAPTABLE_INFO), 
74                                        snap_info->sntbl, &table_size);       
75        
76         if (rc < 0) {
77                 if (rc == -ENOATTR) {
78                         snap_info->sntbl->sntbl_count = 1;
79                         CDEBUG(D_INFO, "No snaptable here\n");
80                         RETURN(0);
81                 } else {
82                         CERROR("Can not retrive the snaptable from this filesystem\n");
83                         OBD_FREE(snap_info->sntbl, table_size);
84                         RETURN(rc); 
85                 }
86         } 
87         if (le32_to_cpu(snap_info->sntbl->sntbl_magic) != SNAP_TABLE_MAGIC) {
88                 CERROR("On disk snaptable is not right \n");
89                 OBD_FREE(snap_info->sntbl, table_size);
90                 RETURN(-EIO);
91         }
92         snap_info->sntbl->sntbl_max_count = size;
93         
94         return 0;
95 }
96
97 int smfs_cow_init(struct super_block *sb)
98 {
99         struct smfs_super_info *smfs_info = S2SMI(sb);
100         struct inode *inode = sb->s_root->d_inode;
101         int rc = 0;
102
103         SMFS_SET_COW(smfs_info);
104         SMFS_SET_INODE_COW(inode);
105       
106         OBD_ALLOC(smfs_info->smsi_snap_info, sizeof(struct snap_info));
107      
108         if (!smfs_info->smsi_snap_info) 
109                 RETURN(-ENOMEM);
110         
111         /*init snap fsfilt operations*/
112         if (!S2SNAPI(sb)->snap_cache_fsfilt) {
113                 char *snap_cache_ftype = NULL;
114                 int   tmp = strlen(S2SMI(sb)->smsi_cache_ftype) + strlen("_snap");
115                 
116                 OBD_ALLOC(snap_cache_ftype, tmp + 1);  
117                 sprintf(snap_cache_ftype, "%s_snap", S2SMI(sb)->smsi_cache_ftype);
118                 S2SNAPI(sb)->snap_cache_fsfilt = fsfilt_get_ops(snap_cache_ftype);
119                 OBD_FREE(snap_cache_ftype, tmp + 1);
120                 if (!S2SNAPI(sb)->snap_cache_fsfilt) {
121                         CERROR("Can not get %s fsfilt ops needed by snap\n",
122                                snap_cache_ftype);
123                         RETURN(-EINVAL);
124                 }
125         }
126         if (!S2SNAPI(sb)->snap_fsfilt) {
127                 char *snap_ftype = NULL;
128                 int   tmp = strlen(S2SMI(sb)->smsi_ftype) + strlen("_snap");
129                 
130                 OBD_ALLOC(snap_ftype, tmp + 1);  
131                 sprintf(snap_ftype, "%s_snap", S2SMI(sb)->smsi_ftype);
132                 S2SNAPI(sb)->snap_fsfilt = fsfilt_get_ops(snap_ftype);
133                 OBD_FREE(snap_ftype, tmp + 1);
134                 if (!S2SNAPI(sb)->snap_fsfilt) {
135                         CERROR("Can not get %s fsfilt ops needed by snap\n",
136                                snap_ftype);
137                         RETURN(-EINVAL);
138                 }
139         }
140         rc = smfs_init_snaptabe(sb); 
141         
142         RETURN(rc);
143 }
144
145 int smfs_cow_cleanup(struct super_block *sb)
146 {
147         struct smfs_super_info *smfs_info = S2SMI(sb);
148         struct snap_info       *snap_info = S2SNAPI(sb);        
149         struct inode *inode = sb->s_root->d_inode;
150         int rc = 0;
151         ENTRY;
152
153         SMFS_CLEAN_COW(smfs_info);
154         SMFS_CLEAN_INODE_COW(inode);
155
156         if (snap_info->sntbl) {
157                 int table_size = SNAPTABLE_SIZE(snap_info->sntbl->sntbl_max_count);
158                 OBD_FREE(snap_info->sntbl, table_size);
159         }
160         if (snap_info) 
161                OBD_FREE(snap_info, sizeof(*snap_info)); 
162         
163         RETURN(rc);
164 }
165
166 /* latest snap: returns 
167    -  the index of the latest snapshot before NOW
168    -  hence it returns 0 in case all the volume snapshots lie in the future
169    -  this is the index where a COW will land (will be created) 
170 */
171 void snap_last(struct super_block *sb, struct snap *snap)
172 {
173         struct snap_info *snap_info = S2SNAPI(sb);
174         struct snap_table *table = snap_info->sntbl;
175         time_t now = CURRENT_TIME;
176         int i ;
177
178         ENTRY;
179         /* start at the highest index in the superblock snaptime array */ 
180         i = table->sntbl_count - 1;
181
182         snap->sn_index = table->sntbl_items[i].sn_index;
183         snap->sn_time = table->sntbl_items[i].sn_time;
184         snap->sn_gen = table->sntbl_items[i].sn_gen;
185         CDEBUG(D_INFO, "index: %d, time[i]: %ld, now: %ld\n",
186                snap->sn_index, snap->sn_time, now);
187         EXIT;
188         return;
189 }
190
191 /*
192  * Note: this function should be differnet with snap_do_cow.
193  * In smfs_do_cow, we check the EA for whether do cow for that inode.
194  * In smfs_needs_cow, we check whether we do need to do cow. 
195  */
196 int smfs_needs_cow(struct inode *inode)
197 {
198         struct smfs_inode_info  *smi_info = I2SMI(inode); 
199         struct snap_inode_info *snap_info = NULL;
200         struct snap snap;
201         int index = -1;
202         ENTRY;
203
204         snap_info = &(smi_info->sm_sninfo);
205         
206         snap_last(inode->i_sb, &snap);
207         /* decision .... if the snapshot is more recent than the object,
208          * then any change to the object should cause a COW.
209          */
210         if (snap_info->sn_gen < snap.sn_gen ) 
211                 index = snap.sn_index;
212
213         CDEBUG(D_INFO, "snap_needs_cow, ino %lu , get index %d\n",
214                inode->i_ino, index);
215
216         RETURN(index);
217 } /* snap_needs_cow */
218
219 /*
220  * Make a copy of the data and plug a redirector in between if there
221  * is no redirector yet.
222  */
223 int snap_do_cow(struct inode *inode, struct dentry *dparent, int del)
224 {
225         struct snap_info *snap_info = S2SNAPI(inode->i_sb);     
226         struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
227         struct snap snap;
228         struct inode *ind = NULL;
229
230         ENTRY;
231
232         if (!snapops || !snapops->fs_create_indirect) 
233                 RETURN(-EINVAL);
234
235         snap_last(inode->i_sb, &snap);
236         ind = snapops->fs_create_indirect(inode, snap.sn_index, snap.sn_gen, 
237                                           dparent->d_inode, del);
238         if(!ind)
239                 RETURN(-EINVAL);
240
241         I2SMI(ind)->sm_sninfo.sn_flags = 0;
242         I2SMI(ind)->sm_sninfo.sn_gen = snap.sn_gen;
243         
244         iput(ind);
245         RETURN(0);
246 }
247
248 int smfs_cow_create(struct inode *dir, struct dentry *dentry)
249 {
250         int rc = 0;
251         ENTRY;
252
253         if (smfs_needs_cow(dir) != -1) {
254                 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
255                 if ((smfs_cow(dir, dentry->d_parent, 0))) {
256                         CERROR("Do cow error\n");
257                         RETURN(-EINVAL);
258                 }
259         }
260         RETURN(rc);
261 }
262
263 int smfs_cow_setattr(struct inode *dir, struct dentry *dentry)
264 {
265         int rc = 0;
266         ENTRY;
267         
268         RETURN(rc);
269 }
270
271 int smfs_cow_link(struct inode *dir, struct dentry *dentry)
272 {
273         int rc = 0;
274         ENTRY;
275         
276         RETURN(rc);
277 }
278
279 int smfs_cow_unlink(struct inode *dir, struct dentry *dentry)
280 {
281         int rc = 0;
282         ENTRY;
283         
284         RETURN(rc);
285 }
286
287 int smfs_cow_rename(struct inode *dir, struct dentry *dentry)
288 {
289         int rc = 0;
290         ENTRY;
291         
292         RETURN(rc);
293 }
294
295 int smfs_cow_write(struct inode *dir, struct dentry *dentry)
296 {
297         int rc = 0;
298         ENTRY;
299         
300         RETURN(rc);
301 }
302
303 typedef int (*cow_funcs)(struct inode *dir, struct dentry *dentry);
304
305 static cow_funcs smfs_cow_funcs[REINT_MAX + 1] = {
306         [REINT_SETATTR] smfs_cow_setattr,
307         [REINT_CREATE]  smfs_cow_create,
308         [REINT_LINK]    smfs_cow_link,
309         [REINT_UNLINK]  smfs_cow_unlink,
310         [REINT_RENAME]  smfs_cow_rename,
311         [REINT_WRITE]   smfs_cow_write,
312 };
313
314 int smfs_cow(struct inode *dir, struct dentry *dentry, int op)
315 {
316         return smfs_cow_funcs[op](dir, dentry);
317 }
318