1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
5 * Lustre filesystem abstraction routines
7 * Copyright (C) 2004 Cluster File Systems, Inc.
9 * This file is part of Lustre, http://www.lustre.org.
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.
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.
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.
25 # define EXPORT_SYMTAB
28 #define DEBUG_SUBSYSTEM S_SM
30 #include <linux/kmod.h>
31 #include <linux/init.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"
42 smfs_pack_rec_func smfs_get_rec_pack_type(struct super_block *sb)
44 struct smfs_super_info *smsi = S2SMI(sb);
46 int index = GET_REC_PACK_TYPE_INDEX(smsi->smsi_flags);
48 return smsi->smsi_pack_rec[index];
50 static int smfs_rec_post_hook(struct inode *inode, struct dentry *dentry,
51 void *data1, void *data2, int op, void *handle)
56 if (smfs_do_rec(inode))
57 rc = smfs_post_kml_rec(inode, dentry, data1, data2, op);
62 #define KML_HOOK "kml_hook"
63 int smfs_rec_init(struct super_block *sb)
65 struct smfs_super_info *smfs_info = S2SMI(sb);
66 struct smfs_hook_ops *rec_hops = NULL;
69 SMFS_SET_REC(smfs_info);
71 ost_rec_pack_init(smfs_info);
72 mds_rec_pack_init(smfs_info);
74 rec_hops = smfs_alloc_hook_ops(KML_HOOK, NULL, smfs_rec_post_hook);
78 rc = smfs_register_hook_ops(smfs_info, rec_hops);
80 smfs_unregister_hook_ops(smfs_info, rec_hops->smh_name);
81 smfs_free_hook_ops(rec_hops);
86 int smfs_rec_cleanup(struct smfs_super_info *smfs_info)
88 struct smfs_hook_ops *rec_hops;
91 rec_hops = smfs_unregister_hook_ops(smfs_info, KML_HOOK);
92 smfs_free_hook_ops(rec_hops);
93 SMFS_CLEAN_REC(smfs_info);
98 static inline void copy_inode_attr(struct iattr *iattr, struct inode *inode)
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;
109 static inline int unpack_rec_data(char **p_buffer, int *size,
110 char *in_data, char *args_data)
116 args_len = strlen(args_data);
118 *size = *((int*)(in_data));
119 rc = *size + sizeof(int);
121 OBD_ALLOC(*p_buffer, *size + args_len + 1);
124 /*First copy reint dir */
126 memcpy(*p_buffer, args_data, args_len);
128 /*then copy the node name */
129 memcpy(*p_buffer + args_len,
130 (in_data + sizeof(int)), *size);
137 int smfs_rec_unpack(struct smfs_proc_args *args, char *record,
138 char **pbuf, int *opcode)
140 int offset = *(int *)(record);
141 char *tmp = record + offset + sizeof(int);
143 *opcode = *(int *)tmp;
144 *pbuf = tmp + sizeof(*opcode);
147 EXPORT_SYMBOL(smfs_rec_unpack);
149 int smfs_start_rec(struct super_block *sb, struct vfsmount *mnt)
151 struct dentry *dentry;
152 struct lvfs_run_ctxt saved;
156 if (SMFS_INIT_REC(S2SMI(sb)) ||
157 (!SMFS_DO_REC(S2SMI(sb)) && !SMFS_CACHE_HOOK(S2SMI(sb))))
160 rc = smfs_llog_setup(sb, mnt);
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);
170 S2SMI(sb)->smsi_delete_dir = dentry;
173 SMFS_SET_INIT_REC(S2SMI(sb));
175 pop_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
178 if (S2SMI(sb)->smsi_ctxt)
179 OBD_FREE(S2SMI(sb)->smsi_ctxt, sizeof(struct lvfs_run_ctxt));
182 EXPORT_SYMBOL(smfs_start_rec);
184 int smfs_post_setup(struct super_block *sb, struct vfsmount *mnt)
186 struct lvfs_run_ctxt *current_ctxt = NULL;
187 struct smfs_super_info *smb = S2SMI(sb);
189 OBD_ALLOC(current_ctxt, sizeof(*current_ctxt));
192 OBD_SET_CTXT_MAGIC(current_ctxt);
194 current_ctxt->pwdmnt = mnt;
195 current_ctxt->pwd = mnt->mnt_root;
196 current_ctxt->fs = get_ds();
197 smb->smsi_ctxt = current_ctxt;
201 EXPORT_SYMBOL(smfs_post_setup);
203 int smfs_post_cleanup(struct super_block *sb)
205 struct smfs_super_info *smb = S2SMI(sb);
210 OBD_FREE(S2SMI(sb)->smsi_ctxt, sizeof(struct lvfs_run_ctxt));
213 EXPORT_SYMBOL(smfs_post_cleanup);
215 int smfs_stop_rec(struct super_block *sb)
219 if (!SMFS_INIT_REC(S2SMI(sb)) ||
220 (!SMFS_DO_REC(S2SMI(sb)) && !SMFS_CACHE_HOOK(S2SMI(sb))))
223 rc = smfs_llog_cleanup(sb);
225 SMFS_CLEAN_INIT_REC(S2SMI(sb));
227 if (S2SMI(sb)->smsi_delete_dir) {
228 l_dput(S2SMI(sb)->smsi_delete_dir);
229 S2SMI(sb)->smsi_delete_dir = NULL;
233 EXPORT_SYMBOL(smfs_stop_rec);
235 int smfs_write_extents(struct inode *dir, struct dentry *dentry,
236 unsigned long from, unsigned long num)
238 return smfs_post_rec_write(dir, dentry, &from, &num);
240 EXPORT_SYMBOL(smfs_write_extents);
242 int smfs_rec_setattr(struct inode *dir, struct dentry *dentry,
245 return smfs_post_rec_setattr(dir, dentry, attr, NULL);
247 EXPORT_SYMBOL(smfs_rec_setattr);
249 int smfs_rec_md(struct inode *inode, void * lmm, int lmm_size)
251 char *set_lmm = NULL;
256 OBD_ALLOC(set_lmm, lmm_size + sizeof(lmm_size));
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);
263 CERROR("Error: Record md for inode %lu rc=%d\n",
268 OBD_FREE(set_lmm, lmm_size + sizeof(lmm_size));
271 EXPORT_SYMBOL(smfs_rec_md);
273 int smfs_rec_precreate(struct dentry *dentry, int *num, struct obdo *oa)
275 return smfs_post_rec_create(dentry->d_inode, dentry, num, oa);
277 EXPORT_SYMBOL(smfs_rec_precreate);
279 int smfs_process_rec(struct super_block *sb,
280 int count, char *dir, int flags)
282 struct llog_ctxt *ctxt;
283 struct llog_handle *loghandle;
284 struct smfs_proc_args args;
287 if (!SMFS_INIT_REC(S2SMI(sb))) {
288 CWARN("Did not start up rec server \n");
292 memset(&args, 0, sizeof(struct smfs_proc_args));
294 args.sr_count = count;
296 args.sr_flags = flags ;
297 ctxt = S2SMI(sb)->smsi_rec_log;
298 loghandle = ctxt->loc_handle;
301 if (SMFS_DO_REINT_REC(flags)) {
302 struct llog_gen_rec *lgr;
304 /*For reint rec, we need insert
305 *a gen rec to identify the end
307 OBD_ALLOC(lgr, sizeof(*lgr));
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,
315 OBD_FREE(lgr, sizeof(*lgr));
320 SET_REC_COUNT_FLAGS(args.sr_flags, SMFS_REC_ALL);
323 if (SMFS_DO_REINT_REC(flags))
324 rc = llog_cat_process(loghandle, ctxt->llog_proc_cb,
327 rc = llog_cat_reverse_process(loghandle,
330 if (rc == LLOG_PROC_BREAK)