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 #define KML_BUF_REC_INIT(buffer, pbuf, len) \
44 pbuf = buffer + sizeof(int); \
48 #define KML_BUF_REC_END(buffer, length, pbuf) \
51 memcpy(buffer, &len, sizeof(len)); \
52 length += sizeof(int); \
53 pbuf = buffer + length; \
56 static smfs_pack_rec_func smfs_get_rec_pack_type(struct super_block *sb)
58 struct smfs_super_info *smsi = S2SMI(sb);
60 int index = GET_REC_PACK_TYPE_INDEX(smsi->smsi_flags);
62 return smsi->smsi_pack_rec[index];
65 static int smfs_post_kml_rec(struct inode *dir, void *de, void *data1,
68 static int smfs_rec_post_hook(struct inode *inode, void *dentry,
69 void *data1, void *data2, int op, void *handle)
74 if (smfs_do_rec(inode))
75 rc = smfs_post_kml_rec(inode, dentry, data1, data2, op);
80 #define KML_HOOK "kml_hook"
81 int smfs_rec_init(struct super_block *sb)
83 struct smfs_super_info *smfs_info = S2SMI(sb);
84 struct smfs_hook_ops *rec_hops = NULL;
87 SMFS_SET_REC(smfs_info);
89 ost_rec_pack_init(smfs_info);
90 mds_rec_pack_init(smfs_info);
92 rec_hops = smfs_alloc_hook_ops(KML_HOOK, NULL, smfs_rec_post_hook);
96 rc = smfs_register_hook_ops(smfs_info, rec_hops);
98 smfs_unregister_hook_ops(smfs_info, rec_hops->smh_name);
99 smfs_free_hook_ops(rec_hops);
104 int smfs_rec_cleanup(struct smfs_super_info *smfs_info)
106 struct smfs_hook_ops *rec_hops;
109 rec_hops = smfs_unregister_hook_ops(smfs_info, KML_HOOK);
110 smfs_free_hook_ops(rec_hops);
111 SMFS_CLEAN_REC(smfs_info);
116 static inline void copy_inode_attr(struct iattr *iattr, struct inode *inode)
118 iattr->ia_mode = inode->i_mode;
119 iattr->ia_uid = inode->i_uid;
120 iattr->ia_gid = inode->i_gid;
121 iattr->ia_atime = inode->i_atime;
122 iattr->ia_ctime = inode->i_ctime;
123 iattr->ia_mtime = inode->i_mtime;
124 iattr->ia_size = inode->i_size;
127 static inline int unpack_rec_data(char **p_buffer, int *size,
128 char *in_data, char *args_data)
134 args_len = strlen(args_data);
136 *size = *((int*)(in_data));
137 rc = *size + sizeof(int);
139 OBD_ALLOC(*p_buffer, *size + args_len + 1);
142 /*First copy reint dir */
144 memcpy(*p_buffer, args_data, args_len);
146 /*then copy the node name */
147 memcpy(*p_buffer + args_len,
148 (in_data + sizeof(int)), *size);
155 int smfs_rec_unpack(struct smfs_proc_args *args, char *record,
156 char **pbuf, int *opcode)
158 int offset = *(int *)(record);
159 char *tmp = record + offset + sizeof(int);
161 *opcode = *(int *)tmp;
162 *pbuf = tmp + sizeof(*opcode);
165 EXPORT_SYMBOL(smfs_rec_unpack);
167 int smfs_start_rec(struct super_block *sb, struct vfsmount *mnt)
169 struct dentry *dentry;
170 struct lvfs_run_ctxt saved;
174 if (SMFS_INIT_REC(S2SMI(sb)) ||
175 (!SMFS_DO_REC(S2SMI(sb)) && !SMFS_CACHE_HOOK(S2SMI(sb))))
178 rc = smfs_llog_setup(sb, mnt);
181 push_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
182 dentry = simple_mkdir(current->fs->pwd, "DELETE", 0777, 1);
183 if (IS_ERR(dentry)) {
184 rc = PTR_ERR(dentry);
185 CERROR("cannot create DELETE directory: rc = %d\n", rc);
186 GOTO(err_exit, rc = -EINVAL);
188 S2SMI(sb)->smsi_delete_dir = dentry;
191 SMFS_SET_INIT_REC(S2SMI(sb));
193 pop_ctxt(&saved, S2SMI(sb)->smsi_ctxt, NULL);
196 if (S2SMI(sb)->smsi_ctxt)
197 OBD_FREE(S2SMI(sb)->smsi_ctxt, sizeof(struct lvfs_run_ctxt));
200 EXPORT_SYMBOL(smfs_start_rec);
202 int smfs_post_setup(struct super_block *sb, struct vfsmount *mnt)
204 struct lvfs_run_ctxt *current_ctxt = NULL;
205 struct smfs_super_info *smb = S2SMI(sb);
207 OBD_ALLOC(current_ctxt, sizeof(*current_ctxt));
210 OBD_SET_CTXT_MAGIC(current_ctxt);
212 current_ctxt->pwdmnt = mnt;
213 current_ctxt->pwd = mnt->mnt_root;
214 current_ctxt->fs = get_ds();
215 smb->smsi_ctxt = current_ctxt;
219 EXPORT_SYMBOL(smfs_post_setup);
221 int smfs_post_cleanup(struct super_block *sb)
223 struct smfs_super_info *smb = S2SMI(sb);
228 OBD_FREE(S2SMI(sb)->smsi_ctxt, sizeof(struct lvfs_run_ctxt));
231 EXPORT_SYMBOL(smfs_post_cleanup);
233 int smfs_stop_rec(struct super_block *sb)
237 if (!SMFS_INIT_REC(S2SMI(sb)) ||
238 (!SMFS_DO_REC(S2SMI(sb)) && !SMFS_CACHE_HOOK(S2SMI(sb))))
241 rc = smfs_llog_cleanup(sb);
243 SMFS_CLEAN_INIT_REC(S2SMI(sb));
245 if (S2SMI(sb)->smsi_delete_dir) {
246 l_dput(S2SMI(sb)->smsi_delete_dir);
247 S2SMI(sb)->smsi_delete_dir = NULL;
251 EXPORT_SYMBOL(smfs_stop_rec);
253 int smfs_write_extents(struct inode *dir, struct dentry *dentry,
254 unsigned long from, unsigned long num)
256 return smfs_post_rec_write(dir, dentry, &from, &num);
258 EXPORT_SYMBOL(smfs_write_extents);
260 int smfs_rec_setattr(struct inode *dir, struct dentry *dentry,
263 return smfs_post_rec_setattr(dir, dentry, attr, NULL);
265 EXPORT_SYMBOL(smfs_rec_setattr);
267 int smfs_rec_md(struct inode *inode, void * lmm, int lmm_size)
269 char *set_lmm = NULL;
274 OBD_ALLOC(set_lmm, lmm_size + sizeof(lmm_size));
277 memcpy(set_lmm, &lmm_size, sizeof(lmm_size));
278 memcpy(set_lmm + sizeof(lmm_size), lmm, lmm_size);
279 rc = smfs_post_rec_setattr(inode, NULL, NULL, set_lmm);
281 CERROR("Error: Record md for inode %lu rc=%d\n",
286 OBD_FREE(set_lmm, lmm_size + sizeof(lmm_size));
289 EXPORT_SYMBOL(smfs_rec_md);
291 int smfs_rec_precreate(struct dentry *dentry, int *num, struct obdo *oa)
293 return smfs_post_rec_create(dentry->d_inode, dentry, num, oa);
295 EXPORT_SYMBOL(smfs_rec_precreate);
297 int smfs_process_rec(struct super_block *sb,
298 int count, char *dir, int flags)
300 struct llog_ctxt *ctxt;
301 struct llog_handle *loghandle;
302 struct smfs_proc_args args;
305 if (!SMFS_INIT_REC(S2SMI(sb))) {
306 CWARN("Did not start up rec server \n");
310 memset(&args, 0, sizeof(struct smfs_proc_args));
312 args.sr_count = count;
314 args.sr_flags = flags ;
315 ctxt = S2SMI(sb)->smsi_rec_log;
316 loghandle = ctxt->loc_handle;
319 if (SMFS_DO_REINT_REC(flags)) {
320 struct llog_gen_rec *lgr;
322 /*For reint rec, we need insert
323 *a gen rec to identify the end
325 OBD_ALLOC(lgr, sizeof(*lgr));
328 lgr->lgr_hdr.lrh_len = lgr->lgr_tail.lrt_len = sizeof(*lgr);
329 lgr->lgr_hdr.lrh_type = LLOG_GEN_REC;
330 lgr->lgr_gen = ctxt->loc_gen;
331 rc = llog_add(ctxt, &lgr->lgr_hdr, NULL, NULL, 1,
333 OBD_FREE(lgr, sizeof(*lgr));
338 SET_REC_COUNT_FLAGS(args.sr_flags, SMFS_REC_ALL);
341 if (SMFS_DO_REINT_REC(flags))
342 rc = llog_cat_process(loghandle, ctxt->llog_proc_cb,
345 rc = llog_cat_reverse_process(loghandle,
348 if (rc == LLOG_PROC_BREAK)
354 /*smfs_path is gotten from intermezzo*/
355 static char* smfs_path(struct dentry *dentry, struct dentry *root, char *buffer,
358 char * end = buffer + buflen;
359 char * name = buffer;
360 char * buf_end = buffer + buflen;
370 struct dentry * parent;
375 parent = dentry->d_parent;
376 if (dentry == parent)
378 namelen = dentry->d_name.len;
379 buflen -= namelen + 1;
383 memcpy(end, dentry->d_name.name, namelen);
389 while (end != buf_end)
395 static int smfs_log_path(struct super_block *sb,
396 struct dentry *dentry,
400 struct dentry *root=sb->s_root;
401 char *p_name = buffer + sizeof(int);
405 name = smfs_path(dentry, root, p_name, buffer_len - sizeof(int));
406 namelen = cpu_to_le32(strlen(p_name));
407 memcpy(buffer, &namelen, sizeof(int));
409 namelen += sizeof(int);
413 static inline int log_it(char *buffer, void *data, int length)
415 memcpy(buffer, &length, sizeof(int));
416 memcpy(buffer + sizeof(int), data, length);
417 return (sizeof(int) + length);
420 static int smfs_pack_rec (char *buffer, struct dentry *dentry,
421 struct inode *dir, void *data1,
424 smfs_pack_rec_func pack_func;
427 pack_func = smfs_get_rec_pack_type(dir->i_sb);
431 rc = pack_func(buffer, dentry, dir, data1, data2, op);
435 int smfs_post_rec_create(struct inode *dir, struct dentry *dentry, void *data1,
438 struct smfs_super_info *sinfo;
439 char *buffer = NULL, *pbuf;
440 int rc = 0, length = 0, buf_len = 0;
442 sinfo = S2SMI(dentry->d_inode->i_sb);
446 OBD_ALLOC(buffer, PAGE_SIZE);
448 GOTO(exit, rc = -ENOMEM);
451 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
452 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
456 KML_BUF_REC_END(buffer, length, pbuf);
458 rc = smfs_pack_rec(pbuf, dentry, dir,
459 data1, data2, REINT_CREATE);
464 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
467 OBD_FREE(buffer, PAGE_SIZE);
472 static int smfs_post_rec_link(struct inode *dir, struct dentry *dentry,
473 void *data1, void *data2)
475 struct smfs_super_info *sinfo;
476 struct dentry *old_dentry = (struct dentry *)data1;
477 char *buffer = NULL, *pbuf = NULL;
478 int rc = 0, length = 0, buf_len = 0;
480 sinfo = S2SMI(dir->i_sb);
483 OBD_ALLOC(buffer, PAGE_SIZE);
485 GOTO(exit, rc = -ENOMEM);
488 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
489 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
494 KML_BUF_REC_END(buffer, length, pbuf);
496 rc = smfs_pack_rec(pbuf, dentry, dir, dentry->d_parent,
497 old_dentry->d_parent, REINT_LINK);
502 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
505 OBD_FREE(buffer, PAGE_SIZE);
510 static int smfs_post_rec_unlink(struct inode *dir, struct dentry *dentry,
511 void *data1, void *data2)
513 struct smfs_super_info *sinfo;
514 int mode = *((int*)data1);
515 char *buffer = NULL, *pbuf = NULL;
516 int length = 0, rc = 0, buf_len = 0;
518 sinfo = S2SMI(dentry->d_inode->i_sb);
522 OBD_ALLOC(buffer, PAGE_SIZE);
524 GOTO(exit, rc = -ENOMEM);
527 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
528 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
533 KML_BUF_REC_END(buffer, length, pbuf);
534 rc = smfs_pack_rec(pbuf, dentry, dir,
535 &mode, NULL, REINT_UNLINK);
541 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
544 OBD_FREE(buffer, PAGE_SIZE);
549 static int smfs_post_rec_rename(struct inode *dir, struct dentry *dentry,
550 void *data1, void *data2)
552 struct smfs_super_info *sinfo;
553 struct inode *new_dir = (struct inode *)data1;
554 struct dentry *new_dentry = (struct dentry *)data2;
555 char *buffer = NULL, *pbuf = NULL;
556 int rc = 0, length = 0, buf_len = 0;
558 sinfo = S2SMI(dir->i_sb);
562 OBD_ALLOC(buffer, PAGE_SIZE);
564 GOTO(exit, rc = -ENOMEM);
567 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
568 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
575 /*record new_dentry path*/
576 rc = smfs_log_path(dir->i_sb, new_dentry, pbuf, buf_len);
581 KML_BUF_REC_END(buffer, length, pbuf);
583 rc = smfs_pack_rec(pbuf, dentry, dir,
584 new_dir, new_dentry, REINT_RENAME);
589 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
592 OBD_FREE(buffer, PAGE_SIZE);
596 static int smfs_insert_extents_ea(struct inode *inode, size_t from, loff_t num)
598 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
601 if (SMFS_INODE_OVER_WRITE(inode))
604 rc = fsfilt->fs_insert_extents_ea(inode, OFF2BLKS(from, inode),
605 SIZE2BLKS(num, inode));
609 static int smfs_remove_extents_ea(struct inode *inode, size_t from, loff_t num)
611 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
614 rc = fsfilt->fs_remove_extents_ea(inode, OFF2BLKS(from, inode),
615 SIZE2BLKS(num, inode));
620 static int smfs_remove_all_extents_ea(struct inode *inode)
622 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
625 rc = fsfilt->fs_remove_extents_ea(inode, 0, 0xffffffff);
628 static int smfs_init_extents_ea(struct inode *inode)
630 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
633 rc = fsfilt->fs_init_extents_ea(inode);
637 static int smfs_set_dirty_flags(struct inode *inode, int flags)
639 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
643 if (SMFS_INODE_OVER_WRITE(inode))
645 /*FIXME later, the blocks needed in journal here will be recalculated*/
646 handle = smfs_trans_start(inode, FSFILT_OP_SETATTR, NULL);
647 if (IS_ERR(handle)) {
648 CERROR("smfs_set_dirty_flag:no space for transaction\n");
651 if ((!SMFS_INODE_DIRTY_WRITE(inode) && (!SMFS_INODE_OVER_WRITE(inode))) ||
652 ((flags == SMFS_OVER_WRITE) && (SMFS_INODE_DIRTY_WRITE(inode)))) {
653 rc = fsfilt->fs_set_xattr(inode, handle, REINT_EXTENTS_FLAGS,
654 &flags, sizeof(int));
658 if (flags == SMFS_OVER_WRITE)
659 SMFS_SET_INODE_OVER_WRITE(inode);
661 SMFS_SET_INODE_DIRTY_WRITE(inode);
663 smfs_trans_commit(inode, handle, 0);
667 int smfs_post_rec_setattr(struct inode *inode, struct dentry *dentry,
668 void *data1, void *data2)
670 struct smfs_super_info *sinfo;
671 struct iattr *attr = (struct iattr *)data1;
672 char *buffer = NULL, *pbuf;
673 int rc = 0, length = 0, buf_len = 0;
675 sinfo = S2SMI(inode->i_sb);
679 OBD_ALLOC(buffer, PAGE_SIZE);
681 GOTO(exit, rc = -ENOMEM);
684 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
685 rc = smfs_log_path(inode->i_sb, dentry, pbuf, buf_len);
690 KML_BUF_REC_END(buffer, length, pbuf);
692 rc = smfs_pack_rec(pbuf, dentry, inode,
693 data1, data2, REINT_SETATTR);
699 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
701 if (attr && attr->ia_valid & ATTR_SIZE) {
702 smfs_remove_extents_ea(inode, attr->ia_size,
704 if (attr->ia_size == 0)
705 smfs_set_dirty_flags(inode, SMFS_OVER_WRITE);
707 smfs_set_dirty_flags(inode, SMFS_DIRTY_WRITE);
712 OBD_FREE(buffer, PAGE_SIZE);
716 static int all_blocks_present_ea(struct inode *inode)
722 int smfs_post_rec_write(struct inode *dir, struct dentry *dentry, void *data1,
725 struct smfs_super_info *sinfo;
726 char *buffer = NULL, *pbuf;
727 int rc = 0, length = 0, buf_len = 0;
729 if (!SMFS_INODE_OVER_WRITE(dentry->d_inode) &&
730 !SMFS_INODE_DIRTY_WRITE(dentry->d_inode)) {
731 sinfo = S2SMI(dentry->d_inode->i_sb);
735 OBD_ALLOC(buffer, PAGE_SIZE);
737 GOTO(exit, rc = -ENOMEM);
740 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
741 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
746 memcpy(buffer, &rc, sizeof(int));
747 length = rc + sizeof(int);
749 rc = smfs_pack_rec(pbuf, dentry, dir,
750 data1, data2, REINT_WRITE);
756 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
759 rc = smfs_init_extents_ea(dentry->d_inode);
763 if (dentry->d_inode->i_size == 0) {
764 smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE);
767 loff_t off = *((loff_t*)data1);
768 size_t count = *((size_t*)data2);
770 rc = smfs_insert_extents_ea(dentry->d_inode, off, count);
773 if (all_blocks_present_ea(dentry->d_inode)){
774 smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE);
775 smfs_remove_all_extents_ea(dentry->d_inode);
777 smfs_set_dirty_flags(dentry->d_inode, SMFS_DIRTY_WRITE);
782 OBD_FREE(buffer, PAGE_SIZE);
786 typedef int (*post_kml_rec)(struct inode *dir, struct dentry *dentry,
787 void *data1, void *data2);
789 static post_kml_rec smfs_kml_post[HOOK_MAX + 1] = {
790 [HOOK_CREATE] smfs_post_rec_create,
792 [HOOK_LINK] smfs_post_rec_link,
793 [HOOK_UNLINK] smfs_post_rec_unlink,
794 [HOOK_SYMLINK] smfs_post_rec_create,
795 [HOOK_MKDIR] smfs_post_rec_create,
796 [HOOK_RMDIR] smfs_post_rec_unlink,
797 [HOOK_MKNOD] smfs_post_rec_create,
798 [HOOK_RENAME] smfs_post_rec_rename,
799 [HOOK_SETATTR] smfs_post_rec_setattr,
800 [HOOK_WRITE] smfs_post_rec_write,
802 static int smfs_post_kml_rec(struct inode *dir, void *de, void *data1,
805 if (smfs_kml_post[op]) {
806 struct dentry *dentry = (struct dentry *)de;
808 return smfs_kml_post[op](dir, dentry, data1, data2);