Whamcloud - gitweb
landing smfs.
[fs/lustre-release.git] / lustre / smfs / kml.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/kmod.h>
26 #include <linux/init.h>
27 #include <linux/fs.h>
28 #include <linux/slab.h>
29 #include <linux/obd_class.h>
30 #include <linux/obd_support.h>
31 #include <linux/lustre_lib.h>
32 #include <linux/lustre_idl.h>
33 #include <linux/lustre_fsfilt.h>
34 #include <linux/lustre_smfs.h>
35 #include "smfs_internal.h"
36
37 /*FIXME there should be more conditions in this check*/
38 int smfs_do_rec(struct inode *inode)
39 {
40         struct super_block *sb = inode->i_sb;
41         struct smfs_super_info *smfs_info = S2SMI(sb);
42
43         if (SMFS_DO_REC(smfs_info) && SMFS_INIT_REC(smfs_info) &&
44             SMFS_DO_INODE_REC(inode))
45                 return 1;
46         return 0;
47 }
48
49 int smfs_rec_init(struct super_block *sb)
50 {
51         struct smfs_super_info *smfs_info = S2SMI(sb);
52         int rc = 0;
53
54         SMFS_SET_REC(smfs_info);
55
56         RETURN(rc);
57 }
58
59 int smfs_rec_cleanup(struct super_block *sb)
60 {
61         int rc = 0;
62
63         SMFS_CLEAN_REC(S2SMI(sb));
64         RETURN(rc);
65 }
66
67 void reint_rec_free(struct reint_record *reint_rec)
68 {
69         if (reint_rec) {
70                 if (reint_rec->rec_data1)
71                         OBD_FREE(reint_rec->rec_data1,
72                                  reint_rec->rec1_size + 1);
73                 if (reint_rec->rec_data2)
74                         OBD_FREE(reint_rec->rec_data2,
75                                  reint_rec->rec2_size + 1);
76
77                 OBD_FREE(reint_rec, sizeof(struct reint_record));
78         }
79 }
80
81 static inline void copy_inode_attr(struct iattr *iattr, struct inode *inode)
82 {
83         iattr->ia_mode = inode->i_mode;
84         iattr->ia_uid  = inode->i_uid;
85         iattr->ia_gid  = inode->i_gid;
86         iattr->ia_atime = inode->i_atime;
87         iattr->ia_ctime = inode->i_ctime;
88         iattr->ia_mtime = inode->i_mtime;
89         iattr->ia_size = inode->i_size;
90 }
91
92 void smfs_rec_pack(struct update_record *rec, struct inode *dst,
93                    void *data, int op)
94 {
95         rec->ur_fsuid = current->fsuid;
96         rec->ur_fsgid = current->fsgid;
97         rec->ur_rdev = dst->i_rdev;
98         rec->ur_opcode = op;
99         copy_inode_attr(&rec->ur_iattr, dst);
100         if (data) {
101                 switch (op) {
102                 case REINT_CREATE:
103                 case REINT_LINK:
104                 case REINT_UNLINK:
105                 case REINT_RENAME: {
106                         struct inode *dir = (struct inode *)data;
107                         copy_inode_attr(&rec->ur_pattr, dir);
108                         break;
109                 }
110                 case REINT_SETATTR: {
111                         struct iattr *attr = (struct iattr *)data;
112                         memcpy(&rec->ur_pattr, attr, sizeof(struct iattr));
113                         break;
114                 }
115                 }
116         }
117 }
118
119 static inline void unpack_attr(struct reint_record *r_rec,
120                                struct update_record *u_rec)
121 {
122         memcpy(&r_rec->u_rec, u_rec, sizeof(struct update_record));
123 }
124
125 static inline int unpack_rec_data(char **p_buffer, int *size,
126                                   char *in_data, char *args_data)
127 {
128         int args_len = 0;
129         int rc = 0;
130         ENTRY;
131
132         if (args_data)
133                 args_len = strlen(args_data);
134
135         *size = *((int*)(in_data));
136         rc = *size + sizeof(int);
137
138         OBD_ALLOC(*p_buffer, *size + args_len + 1);
139         if (!*p_buffer)
140                 RETURN(-ENOMEM);
141         /*First copy reint dir */
142         if (args_data)
143                 memcpy(*p_buffer, args_data, args_len);
144
145         /*then copy the node name */
146         memcpy(*p_buffer + args_len,
147                       (in_data + sizeof(int)), *size);
148
149         *size += args_len;
150
151         RETURN(rc);
152 }
153
154 int smfs_rec_unpack(struct smfs_proc_args *args, struct reint_record *r_rec,
155                     char *rec_buf)
156 {
157         struct update_record *u_rec = (struct update_record *)rec_buf;
158         int rc = 0, length = 0;
159         ENTRY;
160         /*FIXME wangdi, there unpack are so smiliar that
161           *we will put it together later*/
162
163         if (SMFS_DO_WRITE_KML(args->sr_flags))
164                 SET_REC_WRITE_KML_FLAGS(r_rec->u_rec.ur_flags, SMFS_WRITE_KML);
165         unpack_attr(r_rec, u_rec);
166         length += sizeof(struct update_record);
167         rc = unpack_rec_data(&r_rec->rec_data1, &r_rec->rec1_size,
168                              (rec_buf + length), args->sr_data);
169         switch (u_rec->ur_opcode) {
170         case REINT_OPEN:
171         case REINT_CLOSE:
172                 /*record src path which will be passed to reint and undo*/
173                 rc = unpack_rec_data(&r_rec->rec_data2, &r_rec->rec2_size,
174                                      (rec_buf + length), NULL);
175                 break;
176         case REINT_LINK:
177         case REINT_RENAME:
178         case REINT_SETATTR:
179         case REINT_UNLINK:
180         case REINT_CREATE:
181         case REINT_WRITE: {
182                 length += rc;
183                 if (length < u_rec->ur_len) {
184                         char *pre_name;
185                         if (u_rec->ur_opcode == REINT_CREATE ||
186                             u_rec->ur_opcode == REINT_WRITE ||
187                             (u_rec->ur_opcode == REINT_UNLINK &&
188                              SMFS_DO_DEC_LINK(r_rec->u_rec.ur_flags)))
189                                 pre_name = NULL;
190                         else
191                                 pre_name = args->sr_data;
192
193                         rc = unpack_rec_data(&r_rec->rec_data2,
194                                              &r_rec->rec2_size,
195                                              (rec_buf + length), pre_name);
196                 }
197                 break;
198         }
199         }
200         if (rc > 0)
201                 rc = 0;
202
203         RETURN(rc);
204 }
205
206 int smfs_start_rec(struct super_block *sb)
207 {
208         struct dentry *dentry;
209         struct lvfs_run_ctxt saved;
210         int rc = 0;
211         ENTRY;
212
213         if (SMFS_INIT_REC(S2SMI(sb)) ||
214             (!SMFS_DO_REC(S2SMI(sb)) && !SMFS_CACHE_HOOK(S2SMI(sb))))
215                 RETURN(rc);
216
217         rc = smfs_llog_setup(sb);
218         if (rc)
219                 RETURN(rc);
220
221         push_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
222         dentry = simple_mkdir(current->fs->pwd, "DELETE", 0777, 1);
223         if (IS_ERR(dentry)) {
224                 rc = PTR_ERR(dentry);
225                 CERROR("cannot create LOGS directory: rc = %d\n", rc);
226                 GOTO(err_exit, rc = -EINVAL);
227         }
228 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
229         if (list_empty(&dentry->d_hash))
230                 d_rehash(dentry);
231 #else
232         /* FIXME-WANGDI: here should be be something. */
233 #endif
234
235         if (!rc)
236                 SMFS_SET_INIT_REC(S2SMI(sb));
237         S2SMI(sb)->smsi_delete_dir = dentry;
238 exit:
239         pop_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
240         RETURN(rc);
241 err_exit:
242         if (S2SMI(sb)->smsi_ctxt)
243                 OBD_FREE(S2SMI(sb)->smsi_ctxt, sizeof(struct lvfs_run_ctxt));
244         goto exit;
245 }
246
247 int smfs_stop_rec(struct super_block *sb)
248 {
249         int rc = 0;
250         ENTRY;
251
252         if (!SMFS_INIT_REC(S2SMI(sb)) ||
253             (!SMFS_DO_REC(S2SMI(sb)) && !SMFS_CACHE_HOOK(S2SMI(sb))))
254                 RETURN(rc);
255
256         rc = smfs_llog_cleanup(sb);
257
258         SMFS_CLEAN_INIT_REC(S2SMI(sb));
259
260         if (S2SMI(sb)->smsi_delete_dir) {
261                 l_dput(S2SMI(sb)->smsi_delete_dir);
262                 S2SMI(sb)->smsi_delete_dir = NULL;
263         }
264         RETURN(rc);
265 }
266
267 int smfs_process_rec(struct super_block *sb, int count, char *dir, int flags)
268 {
269         struct llog_ctxt *ctxt;
270         struct llog_handle *loghandle;
271         struct smfs_proc_args args;
272         int rc = 0;
273         ENTRY;
274
275         if (!SMFS_INIT_REC(S2SMI(sb))) {
276                 CWARN("Did not start up rec server \n");
277                 RETURN(rc);
278         }
279
280         memset(&args, 0, sizeof(struct smfs_proc_args));
281         args.sr_sb = sb;
282         args.sr_count = count;
283         args.sr_data = dir;
284         args.sr_flags = flags ;
285         ctxt = S2SMI(sb)->smsi_rec_log;
286         loghandle = ctxt->loc_handle;
287
288         if (count == 0) {
289                 if (SMFS_DO_REINT_REC(flags)) {
290                         struct llog_gen_rec *lgr;
291
292                         /*For reint rec, we need insert
293                           *a gen rec to identify the end
294                           *of the rec.*/
295                         OBD_ALLOC(lgr, sizeof(*lgr));
296                         if (!lgr)
297                                 RETURN(-ENOMEM);
298                         lgr->lgr_hdr.lrh_len = lgr->lgr_tail.lrt_len =
299                                 sizeof(*lgr);
300                         lgr->lgr_hdr.lrh_type = LLOG_GEN_REC;
301                         lgr->lgr_gen = ctxt->loc_gen;
302                         rc = llog_add(ctxt, &lgr->lgr_hdr, NULL, NULL, 1, NULL);
303                         OBD_FREE(lgr, sizeof(*lgr));
304                         if (rc != 1)
305                                 RETURN(rc);
306                 }
307         } else {
308                 SET_REC_COUNT_FLAGS(args.sr_flags, SMFS_REC_ALL);
309         }
310         if (loghandle) {
311                 if (SMFS_DO_REINT_REC(flags))
312                         rc = llog_cat_process(loghandle, ctxt->loc_proc_cb,
313                                               (void *)&args);
314                 else
315                         rc = llog_cat_reverse_process(loghandle,
316                                                       ctxt->loc_proc_cb,
317                                                       (void *)&args);
318                 if (rc == LLOG_PROC_BREAK)
319                         rc = 0;
320         }
321         RETURN(rc);
322 }