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