Whamcloud - gitweb
update .snap on 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  *  lustre/smfs/kml.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 #ifndef EXPORT_SYMTAB
25 # define EXPORT_SYMTAB
26 #endif
27
28 #define DEBUG_SUBSYSTEM S_SM
29
30 #include <linux/kmod.h>
31 #include <linux/init.h>
32 #include <linux/fs.h>
33 #include <linux/slab.h>
34 #include <linux/obd_class.h>
35 #include <linux/obd_support.h>
36 #include <linux/lustre_lib.h>
37 #include <linux/lustre_idl.h>
38 #include <linux/lustre_fsfilt.h>
39 #include <linux/lustre_smfs.h>
40 #include "smfs_internal.h"
41
42 smfs_pack_rec_func smfs_get_rec_pack_type(struct super_block *sb)
43 {
44         struct smfs_super_info *smsi = S2SMI(sb);
45
46         int index = GET_REC_PACK_TYPE_INDEX(smsi->smsi_flags);
47
48         return smsi->smsi_pack_rec[index];
49 }
50 static int smfs_rec_post_hook(struct inode *inode, struct dentry *dentry,
51                               void *data1, void *data2, int op, void *handle)
52 {
53         int rc = 0;
54         ENTRY;
55
56         if (smfs_do_rec(inode))                                  
57                 rc = smfs_post_kml_rec(inode, dentry, data1, data2, op);  
58         
59         RETURN(rc);
60 }
61
62 #define KML_HOOK "kml_hook"
63 int smfs_rec_init(struct super_block *sb)
64 {
65         struct smfs_super_info *smfs_info = S2SMI(sb);
66         struct smfs_hook_ops   *rec_hops = NULL;
67         int rc = 0;
68
69         SMFS_SET_REC(smfs_info);
70
71         ost_rec_pack_init(smfs_info);
72         mds_rec_pack_init(smfs_info);
73
74         rec_hops = smfs_alloc_hook_ops(KML_HOOK, NULL, smfs_rec_post_hook);
75         if (!rec_hops) {
76                 RETURN(-ENOMEM);
77         }
78         rc = smfs_register_hook_ops(smfs_info, rec_hops);
79         if (rc && rec_hops) {
80                 smfs_unregister_hook_ops(smfs_info, rec_hops->smh_name);
81                 smfs_free_hook_ops(rec_hops);
82         } 
83         RETURN(rc);
84 }
85
86 int smfs_rec_cleanup(struct smfs_super_info *smfs_info)
87 {
88         struct smfs_hook_ops *rec_hops; 
89         int rc = 0;
90
91         rec_hops = smfs_unregister_hook_ops(smfs_info, KML_HOOK);
92         smfs_free_hook_ops(rec_hops);
93         SMFS_CLEAN_REC(smfs_info);
94         
95         RETURN(rc);
96 }
97
98 static inline void copy_inode_attr(struct iattr *iattr, struct inode *inode)
99 {
100         iattr->ia_mode = inode->i_mode;
101         iattr->ia_uid  = inode->i_uid;
102         iattr->ia_gid  = inode->i_gid;
103         iattr->ia_atime = inode->i_atime;
104         iattr->ia_ctime = inode->i_ctime;
105         iattr->ia_mtime = inode->i_mtime;
106         iattr->ia_size = inode->i_size;
107 }
108
109 static inline int unpack_rec_data(char **p_buffer, int *size,
110                                   char *in_data, char *args_data)
111 {
112         int args_len = 0;
113         int rc = 0;
114
115         if (args_data)
116                 args_len = strlen(args_data);
117
118         *size = *((int*)(in_data));
119         rc = *size + sizeof(int);
120
121         OBD_ALLOC(*p_buffer, *size + args_len + 1);
122         if (!*p_buffer)
123                 RETURN(-ENOMEM);
124         /*First copy reint dir */
125         if (args_data)
126                 memcpy(*p_buffer, args_data, args_len);
127
128         /*then copy the node name */
129         memcpy(*p_buffer + args_len,
130                       (in_data + sizeof(int)), *size);
131
132         *size += args_len;
133
134         RETURN(rc);
135 }
136
137 int smfs_rec_unpack(struct smfs_proc_args *args, char *record, 
138                     char **pbuf, int *opcode)
139 {
140         int offset = *(int *)(record);
141         char *tmp = record + offset + sizeof(int);
142         int rc = 0;
143         *opcode = *(int *)tmp;
144         *pbuf = tmp + sizeof(*opcode);
145         RETURN(rc);
146 }
147 EXPORT_SYMBOL(smfs_rec_unpack);
148
149 int smfs_start_rec(struct super_block *sb, struct vfsmount *mnt)
150 {
151         struct dentry *dentry;
152         struct lvfs_run_ctxt saved;
153         int rc = 0;
154         ENTRY;
155
156         if (SMFS_INIT_REC(S2SMI(sb)) ||
157             (!SMFS_DO_REC(S2SMI(sb)) && !SMFS_CACHE_HOOK(S2SMI(sb))))
158                 RETURN(rc);
159         
160         rc = smfs_llog_setup(sb, mnt);
161         if (rc)
162                 RETURN(rc); 
163         push_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
164         dentry = simple_mkdir(current->fs->pwd, "DELETE", 0777, 1);
165         if (IS_ERR(dentry)) {
166                 rc = PTR_ERR(dentry);
167                 CERROR("cannot create DELETE directory: rc = %d\n", rc);
168                 GOTO(err_exit, rc = -EINVAL);
169         }
170         S2SMI(sb)->smsi_delete_dir = dentry;
171
172         if (!rc)
173                 SMFS_SET_INIT_REC(S2SMI(sb));
174 exit:
175         pop_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
176         RETURN(rc);
177 err_exit:
178         if (S2SMI(sb)->smsi_ctxt)
179                 OBD_FREE(S2SMI(sb)->smsi_ctxt, sizeof(struct lvfs_run_ctxt));
180         goto exit;
181 }
182 EXPORT_SYMBOL(smfs_start_rec);
183
184 int smfs_post_setup(struct super_block *sb, struct vfsmount *mnt)
185 {
186         struct lvfs_run_ctxt *current_ctxt = NULL;
187         struct smfs_super_info *smb = S2SMI(sb);
188  
189         OBD_ALLOC(current_ctxt, sizeof(*current_ctxt));
190         if (!current_ctxt)
191                 RETURN(-ENOMEM);
192         OBD_SET_CTXT_MAGIC(current_ctxt);
193         
194         current_ctxt->pwdmnt = mnt;
195         current_ctxt->pwd = mnt->mnt_root;
196         current_ctxt->fs = get_ds();
197         smb->smsi_ctxt = current_ctxt;
198
199         RETURN(0);
200 }
201 EXPORT_SYMBOL(smfs_post_setup);
202
203 int smfs_post_cleanup(struct super_block *sb)
204 {
205         struct smfs_super_info *smb = S2SMI(sb);
206         
207         ENTRY;
208        
209         if (smb->smsi_ctxt)
210                 OBD_FREE(S2SMI(sb)->smsi_ctxt, sizeof(struct lvfs_run_ctxt));
211         RETURN(0);
212 }
213 EXPORT_SYMBOL(smfs_post_cleanup);
214
215 int smfs_stop_rec(struct super_block *sb)
216 {
217         int rc = 0;
218
219         if (!SMFS_INIT_REC(S2SMI(sb)) ||
220             (!SMFS_DO_REC(S2SMI(sb)) && !SMFS_CACHE_HOOK(S2SMI(sb))))
221                 RETURN(rc);
222
223         rc = smfs_llog_cleanup(sb);
224
225         SMFS_CLEAN_INIT_REC(S2SMI(sb));
226
227         if (S2SMI(sb)->smsi_delete_dir) {
228                 l_dput(S2SMI(sb)->smsi_delete_dir);
229                 S2SMI(sb)->smsi_delete_dir = NULL;
230         }
231         RETURN(rc);
232 }
233 EXPORT_SYMBOL(smfs_stop_rec);
234
235 int smfs_write_extents(struct inode *dir, struct dentry *dentry,
236                        unsigned long from, unsigned long num)
237 {
238         return smfs_post_rec_write(dir, dentry, &from, &num);
239 }
240 EXPORT_SYMBOL(smfs_write_extents);
241
242 int smfs_rec_setattr(struct inode *dir, struct dentry *dentry,
243                      struct iattr *attr)
244 {
245         return smfs_post_rec_setattr(dir, dentry, attr, NULL);
246 }
247 EXPORT_SYMBOL(smfs_rec_setattr);
248
249 int smfs_rec_md(struct inode *inode, void * lmm, int lmm_size)
250 {
251         char *set_lmm = NULL;
252         int  rc = 0;
253         ENTRY;
254
255         if (lmm) {
256                 OBD_ALLOC(set_lmm, lmm_size + sizeof(lmm_size));
257                 if (!set_lmm)
258                         RETURN(-ENOMEM);
259                 memcpy(set_lmm, &lmm_size, sizeof(lmm_size));
260                 memcpy(set_lmm + sizeof(lmm_size), lmm, lmm_size);
261                 rc = smfs_post_rec_setattr(inode, NULL, NULL, set_lmm);
262                 if (rc) {
263                         CERROR("Error: Record md for inode %lu rc=%d\n",
264                                 inode->i_ino, rc);
265                 }
266         }
267         if (set_lmm)
268                 OBD_FREE(set_lmm, lmm_size + sizeof(lmm_size));
269         return rc;
270 }
271 EXPORT_SYMBOL(smfs_rec_md);
272
273 int smfs_rec_precreate(struct dentry *dentry, int *num, struct obdo *oa)
274 {
275        return smfs_post_rec_create(dentry->d_inode, dentry, num, oa);
276 }
277 EXPORT_SYMBOL(smfs_rec_precreate);
278
279 int smfs_process_rec(struct super_block *sb,
280                      int count, char *dir, int flags)
281 {
282         struct llog_ctxt *ctxt;
283         struct llog_handle *loghandle;
284         struct smfs_proc_args args;
285         int rc = 0;
286
287         if (!SMFS_INIT_REC(S2SMI(sb))) {
288                 CWARN("Did not start up rec server \n");
289                 RETURN(rc);
290         }
291
292         memset(&args, 0, sizeof(struct smfs_proc_args));
293         args.sr_sb = sb;
294         args.sr_count = count;
295         args.sr_data = dir;
296         args.sr_flags = flags ;
297         ctxt = S2SMI(sb)->smsi_rec_log;
298         loghandle = ctxt->loc_handle;
299
300         if (count == 0) {
301                 if (SMFS_DO_REINT_REC(flags)) {
302                         struct llog_gen_rec *lgr;
303
304                         /*For reint rec, we need insert
305                           *a gen rec to identify the end
306                           *of the rec.*/
307                         OBD_ALLOC(lgr, sizeof(*lgr));
308                         if (!lgr)
309                                 RETURN(-ENOMEM);
310                         lgr->lgr_hdr.lrh_len = lgr->lgr_tail.lrt_len = sizeof(*lgr);
311                         lgr->lgr_hdr.lrh_type = LLOG_GEN_REC;
312                         lgr->lgr_gen = ctxt->loc_gen;
313                         rc = llog_add(ctxt, &lgr->lgr_hdr, NULL, NULL, 1,
314                                       NULL, NULL, NULL);
315                         OBD_FREE(lgr, sizeof(*lgr));
316                         if (rc != 1)
317                                 RETURN(rc);
318                 }
319         } else {
320                 SET_REC_COUNT_FLAGS(args.sr_flags, SMFS_REC_ALL);
321         }
322         if (loghandle) {
323                 if (SMFS_DO_REINT_REC(flags))
324                         rc = llog_cat_process(loghandle, ctxt->llog_proc_cb,
325                                               (void *)&args);
326                 else
327                         rc = llog_cat_reverse_process(loghandle,
328                                                       ctxt->llog_proc_cb,
329                                                       (void *)&args);
330                 if (rc == LLOG_PROC_BREAK)
331                         rc = 0;
332         }
333         RETURN(rc);
334 }