1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2004 Cluster File Systems, Inc.
6 * This file is part of Lustre, http://www.lustre.org.
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.
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.
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.
23 #define DEBUG_SUBSYSTEM S_SM
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>
38 #include <linux/lustre_snap.h>
39 #include <linux/lustre_smfs.h>
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)
45 struct snap_info *snap_info = S2SNAPI(sb);
46 struct snap_table *snap_table = NULL;
47 struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
48 int rc = 0, size, table_size, vallen;
52 init_MUTEX(&snap_info->sntbl_sema);
53 /*Initialized table */
54 /*get the maxsize of snaptable*/
56 rc = snapops->fs_get_snap_info(sb, NULL, MAX_SNAPTABLE_COUNT,
57 strlen(MAX_SNAPTABLE_COUNT), &size,
60 CERROR("the Max snaptable count should not be zero\n");
64 table_size = SNAPTABLE_SIZE(size);
66 OBD_ALLOC(snap_info->sntbl, table_size);
68 if (!snap_info->sntbl) {
72 snap_table = snap_info->sntbl;
74 snap_table->sntbl_magic = cpu_to_le32((__u32)SNAPTABLE_MAGIC);
75 snap_table->sntbl_max_count = size;
76 /*get snaptable info*/
78 rc = snapops->fs_get_snap_info(sb, NULL, SNAPTABLE_INFO,
79 strlen(SNAPTABLE_INFO),
80 snap_table, &table_size);
83 snap_table->sntbl_count = 0;
84 CDEBUG(D_INFO, "No snaptable here\n");
87 CERROR("Can not retrive the snaptable from this filesystem\n");
88 OBD_FREE(snap_table, table_size);
92 if (le32_to_cpu(snap_table->sntbl_magic) != SNAPTABLE_MAGIC) {
93 CERROR("On disk snaptable is not right \n");
94 OBD_FREE(snap_table, table_size);
100 int smfs_cow_init(struct super_block *sb)
102 struct smfs_super_info *smfs_info = S2SMI(sb);
103 struct inode *inode = sb->s_root->d_inode;
106 SMFS_SET_COW(smfs_info);
108 OBD_ALLOC(smfs_info->smsi_snap_info, sizeof(struct snap_info));
110 if (!smfs_info->smsi_snap_info)
113 /*init snap fsfilt operations*/
114 if (!S2SNAPI(sb)->snap_cache_fsfilt) {
115 char *snap_cache_ftype = NULL;
116 int tmp = strlen(S2SMI(sb)->smsi_cache_ftype) + strlen("_snap");
118 OBD_ALLOC(snap_cache_ftype, tmp + 1);
119 sprintf(snap_cache_ftype, "%s_snap", S2SMI(sb)->smsi_cache_ftype);
120 S2SNAPI(sb)->snap_cache_fsfilt = fsfilt_get_ops(snap_cache_ftype);
121 OBD_FREE(snap_cache_ftype, tmp + 1);
122 if (!S2SNAPI(sb)->snap_cache_fsfilt) {
123 CERROR("Can not get %s fsfilt ops needed by snap\n",
128 if (!S2SNAPI(sb)->snap_fsfilt) {
129 char *snap_ftype = NULL;
130 int tmp = strlen(S2SMI(sb)->smsi_ftype) + strlen("_snap");
132 OBD_ALLOC(snap_ftype, tmp + 1);
133 sprintf(snap_ftype, "%s_snap", S2SMI(sb)->smsi_ftype);
134 S2SNAPI(sb)->snap_fsfilt = fsfilt_get_ops(snap_ftype);
135 OBD_FREE(snap_ftype, tmp + 1);
136 if (!S2SNAPI(sb)->snap_fsfilt) {
137 CERROR("Can not get %s fsfilt ops needed by snap\n",
142 rc = smfs_init_snaptabe(sb);
147 int smfs_cow_cleanup(struct super_block *sb)
149 struct smfs_super_info *smfs_info = S2SMI(sb);
150 struct snap_info *snap_info = S2SNAPI(sb);
151 struct snap_table *snap_table = snap_info->sntbl;
152 int rc = 0, table_size;
155 SMFS_CLEAN_COW(smfs_info);
157 if (snap_info->snap_fsfilt)
158 fsfilt_put_ops(snap_info->snap_fsfilt);
159 if (snap_info->snap_cache_fsfilt)
160 fsfilt_put_ops(snap_info->snap_cache_fsfilt);
163 table_size = SNAPTABLE_SIZE(snap_table->sntbl_max_count);
164 OBD_FREE(snap_info->sntbl, table_size);
167 OBD_FREE(snap_info, sizeof(*snap_info));
172 /*FIXME Note indirect and primary inode
173 * should be recorgnized here*/
174 int smfs_init_snap_inode_info(struct inode *inode, int flags)
176 struct snap_inode_info *sni_info = I2SNAPI(inode);
177 struct fsfilt_operations *snapops = I2SNAPOPS(inode);
181 if (SMFS_DO_COW(S2SMI(inode->i_sb)) &&
182 (flags & SM_DO_COW)) {
183 sni_info->sn_flags = flags;
184 vallen = sizeof(sni_info->sn_gen);
186 rc = snapops->fs_get_snap_info(NULL, inode, SNAP_GENERATION,
187 strlen(SNAP_GENERATION),
188 &sni_info->sn_gen, &vallen);
193 /* latest snap: returns
194 - the index of the latest snapshot before NOW
195 - hence it returns 0 in case all the volume snapshots lie in the future
196 - this is the index where a COW will land (will be created)
198 void snap_last(struct super_block *sb, struct snap *snap)
200 struct snap_info *snap_info = S2SNAPI(sb);
201 struct snap_table *table = snap_info->sntbl;
202 time_t now = CURRENT_TIME;
206 /* start at the highest index in the superblock snaptime array */
207 if (table->sntbl_count == 0) {
208 memset(snap, 0, sizeof(struct snap));
210 i = table->sntbl_count - 1;
211 snap->sn_index = table->sntbl_items[i].sn_index;
212 snap->sn_time = table->sntbl_items[i].sn_time;
213 snap->sn_gen = table->sntbl_items[i].sn_gen;
215 CDEBUG(D_INFO, "index: %d, time[i]: %ld, now: %ld\n",
216 snap->sn_index, snap->sn_time, now);
221 static int inline get_index_of_item(struct snap_table *table, char *name)
223 int count = table->sntbl_count;
227 for (i = 0; i < table->sntbl_max_count; i++) {
228 if (!strcmp(name, table->sntbl_items[i].sn_name)) {
229 CERROR("Duplicate name %s in snaptable\n", name);
234 for (i = 0; i < table->sntbl_max_count; i++) {
236 for (j = 0; j < (count + 1); j++) {
237 if (table->sntbl_items[j].sn_index == i) {
245 CERROR("snaptable Full\n");
249 int smfs_add_snap_item(struct super_block *sb, char *name)
251 struct snap_info *snap_info = S2SNAPI(sb);
252 struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
253 struct snap_table *snap_table = snap_info->sntbl;
254 struct snap *snap_item;
255 int table_size, count = 0, index = 0, rc = 0;
257 count = snap_table->sntbl_count;
258 /* XXX Is down this sema necessary*/
259 down_interruptible(&snap_info->sntbl_sema);
260 snap_item = &snap_table->sntbl_items[count];
262 /*add item in snap_table set generation*/
263 snap_item->sn_time = CURRENT_TIME;
264 /* find table index */
265 index = get_index_of_item(snap_table, name);
267 GOTO(exit, rc = index);
269 snap_item->sn_index = index;
270 snap_item->sn_flags = 0;
271 snap_item->sn_gen = snap_table->sntbl_generation + 1;
272 memcpy(snap_item->sn_name, name, SNAP_MAX_NAMELEN);
273 /* Wrote the whole snap_table to disk */
274 table_size = SNAPTABLE_SIZE(snap_table->sntbl_max_count);
276 rc = snapops->fs_set_snap_info(sb, NULL, SNAPTABLE_INFO,
277 strlen(SNAPTABLE_INFO),
278 snap_table, &table_size);
280 CERROR("Set snaptable error rc=%d\n", rc);
283 snap_table->sntbl_count++;
284 snap_table->sntbl_generation++;
286 up(&snap_info->sntbl_sema);
289 EXPORT_SYMBOL(smfs_add_snap_item);
291 * Note: this function should be differnet with snap_do_cow.
292 * In smfs_do_cow, we check the EA for whether do cow for that inode.
293 * In smfs_needs_cow, we check whether we do need to do cow.
295 int smfs_needs_cow(struct inode *inode)
297 struct smfs_inode_info *smi_info = I2SMI(inode);
298 struct snap_inode_info *snap_info = NULL;
303 snap_info = &(smi_info->sm_sninfo);
305 snap_last(inode->i_sb, &snap);
306 /* decision .... if the snapshot is more recent than the object,
307 * then any change to the object should cause a COW.
309 if (snap_info->sn_gen < snap.sn_gen )
310 index = snap.sn_index;
312 CDEBUG(D_INFO, "snap_needs_cow, ino %lu , get index %d\n",
313 inode->i_ino, index);
316 } /* snap_needs_cow */
319 * Make a copy of the data and plug a redirector in between if there
320 * is no redirector yet.
322 int snap_do_cow(struct inode *inode, struct dentry *dparent, int del)
324 struct snap_info *snap_info = S2SNAPI(inode->i_sb);
325 struct fsfilt_operations *snapops = snap_info->snap_fsfilt;
327 struct inode *ind = NULL;
331 if (!snapops || !snapops->fs_create_indirect)
334 snap_last(inode->i_sb, &snap);
335 ind = snapops->fs_create_indirect(inode, snap.sn_index, snap.sn_gen,
336 dparent->d_inode, del);
340 I2SMI(ind)->sm_sninfo.sn_flags = 0;
341 I2SMI(ind)->sm_sninfo.sn_gen = snap.sn_gen;
347 int smfs_cow_create(struct inode *dir, struct dentry *dentry)
352 if (smfs_needs_cow(dir) != -1) {
353 CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
354 if ((snap_do_cow(dir, dentry->d_parent, 0))) {
355 CERROR("Do cow error\n");
362 int smfs_cow_setattr(struct inode *dir, struct dentry *dentry)
370 int smfs_cow_link(struct inode *dir, struct dentry *dentry)
378 int smfs_cow_unlink(struct inode *dir, struct dentry *dentry)
386 int smfs_cow_rename(struct inode *dir, struct dentry *dentry)
394 int smfs_cow_write(struct inode *dir, struct dentry *dentry)
402 typedef int (*cow_funcs)(struct inode *dir, struct dentry *dentry);
404 static cow_funcs smfs_cow_funcs[REINT_MAX + 1] = {
405 [REINT_SETATTR] smfs_cow_setattr,
406 [REINT_CREATE] smfs_cow_create,
407 [REINT_LINK] smfs_cow_link,
408 [REINT_UNLINK] smfs_cow_unlink,
409 [REINT_RENAME] smfs_cow_rename,
410 [REINT_WRITE] smfs_cow_write,
413 int smfs_cow(struct inode *dir, struct dentry *dentry, int op)
415 return smfs_cow_funcs[op](dir, dentry);