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;
273 if (!SMFS_DO_REC(S2SMI(inode->i_sb)))
277 OBD_ALLOC(set_lmm, lmm_size + sizeof(lmm_size));
280 memcpy(set_lmm, &lmm_size, sizeof(lmm_size));
281 memcpy(set_lmm + sizeof(lmm_size), lmm, lmm_size);
282 rc = smfs_post_rec_setattr(inode, NULL, NULL, set_lmm);
284 CERROR("Error: Record md for inode %lu rc=%d\n",
289 OBD_FREE(set_lmm, lmm_size + sizeof(lmm_size));
292 EXPORT_SYMBOL(smfs_rec_md);
294 int smfs_rec_precreate(struct dentry *dentry, int *num, struct obdo *oa)
296 return smfs_post_rec_create(dentry->d_inode, dentry, num, oa);
298 EXPORT_SYMBOL(smfs_rec_precreate);
300 int smfs_process_rec(struct super_block *sb,
301 int count, char *dir, int flags)
303 struct llog_ctxt *ctxt;
304 struct llog_handle *loghandle;
305 struct smfs_proc_args args;
308 if (!SMFS_INIT_REC(S2SMI(sb))) {
309 CWARN("Did not start up rec server \n");
313 memset(&args, 0, sizeof(struct smfs_proc_args));
315 args.sr_count = count;
317 args.sr_flags = flags ;
318 ctxt = S2SMI(sb)->smsi_rec_log;
319 loghandle = ctxt->loc_handle;
322 if (SMFS_DO_REINT_REC(flags)) {
323 struct llog_gen_rec *lgr;
325 /*For reint rec, we need insert
326 *a gen rec to identify the end
328 OBD_ALLOC(lgr, sizeof(*lgr));
331 lgr->lgr_hdr.lrh_len = lgr->lgr_tail.lrt_len = sizeof(*lgr);
332 lgr->lgr_hdr.lrh_type = LLOG_GEN_REC;
333 lgr->lgr_gen = ctxt->loc_gen;
334 rc = llog_add(ctxt, &lgr->lgr_hdr, NULL, NULL, 1,
336 OBD_FREE(lgr, sizeof(*lgr));
341 SET_REC_COUNT_FLAGS(args.sr_flags, SMFS_REC_ALL);
344 if (SMFS_DO_REINT_REC(flags))
345 rc = llog_cat_process(loghandle, ctxt->llog_proc_cb,
348 rc = llog_cat_reverse_process(loghandle,
351 if (rc == LLOG_PROC_BREAK)
357 /*smfs_path is gotten from intermezzo*/
358 static char* smfs_path(struct dentry *dentry, struct dentry *root, char *buffer,
361 char * end = buffer + buflen;
362 char * name = buffer;
363 char * buf_end = buffer + buflen;
373 struct dentry * parent;
378 parent = dentry->d_parent;
379 if (dentry == parent)
381 namelen = dentry->d_name.len;
382 buflen -= namelen + 1;
386 memcpy(end, dentry->d_name.name, namelen);
392 while (end != buf_end)
398 static int smfs_log_path(struct super_block *sb,
399 struct dentry *dentry,
403 struct dentry *root=sb->s_root;
404 char *p_name = buffer + sizeof(int);
408 name = smfs_path(dentry, root, p_name, buffer_len - sizeof(int));
409 namelen = cpu_to_le32(strlen(p_name));
410 memcpy(buffer, &namelen, sizeof(int));
412 namelen += sizeof(int);
416 static inline int log_it(char *buffer, void *data, int length)
418 memcpy(buffer, &length, sizeof(int));
419 memcpy(buffer + sizeof(int), data, length);
420 return (sizeof(int) + length);
423 static int smfs_pack_rec (char *buffer, struct dentry *dentry,
424 struct inode *dir, void *data1,
427 smfs_pack_rec_func pack_func;
430 pack_func = smfs_get_rec_pack_type(dir->i_sb);
434 rc = pack_func(buffer, dentry, dir, data1, data2, op);
438 int smfs_post_rec_create(struct inode *dir, struct dentry *dentry, void *data1,
441 struct smfs_super_info *sinfo;
442 char *buffer = NULL, *pbuf;
443 int rc = 0, length = 0, buf_len = 0;
445 sinfo = S2SMI(dentry->d_inode->i_sb);
449 OBD_ALLOC(buffer, PAGE_SIZE);
451 GOTO(exit, rc = -ENOMEM);
454 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
455 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
459 KML_BUF_REC_END(buffer, length, pbuf);
461 rc = smfs_pack_rec(pbuf, dentry, dir,
462 data1, data2, REINT_CREATE);
467 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
470 OBD_FREE(buffer, PAGE_SIZE);
475 static int smfs_post_rec_link(struct inode *dir, struct dentry *dentry,
476 void *data1, void *data2)
478 struct smfs_super_info *sinfo;
479 struct dentry *old_dentry = (struct dentry *)data1;
480 char *buffer = NULL, *pbuf = NULL;
481 int rc = 0, length = 0, buf_len = 0;
483 sinfo = S2SMI(dir->i_sb);
486 OBD_ALLOC(buffer, PAGE_SIZE);
488 GOTO(exit, rc = -ENOMEM);
491 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
492 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
497 KML_BUF_REC_END(buffer, length, pbuf);
499 rc = smfs_pack_rec(pbuf, dentry, dir, dentry->d_parent,
500 old_dentry->d_parent, REINT_LINK);
505 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
508 OBD_FREE(buffer, PAGE_SIZE);
513 static int smfs_post_rec_unlink(struct inode *dir, struct dentry *dentry,
514 void *data1, void *data2)
516 struct smfs_super_info *sinfo;
517 int mode = *((int*)data1);
518 char *buffer = NULL, *pbuf = NULL;
519 int length = 0, rc = 0, buf_len = 0;
521 sinfo = S2SMI(dentry->d_inode->i_sb);
525 OBD_ALLOC(buffer, PAGE_SIZE);
527 GOTO(exit, rc = -ENOMEM);
530 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
531 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
536 KML_BUF_REC_END(buffer, length, pbuf);
537 rc = smfs_pack_rec(pbuf, dentry, dir,
538 &mode, NULL, REINT_UNLINK);
544 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
547 OBD_FREE(buffer, PAGE_SIZE);
552 static int smfs_post_rec_rename(struct inode *dir, struct dentry *dentry,
553 void *data1, void *data2)
555 struct smfs_super_info *sinfo;
556 struct inode *new_dir = (struct inode *)data1;
557 struct dentry *new_dentry = (struct dentry *)data2;
558 char *buffer = NULL, *pbuf = NULL;
559 int rc = 0, length = 0, buf_len = 0;
561 sinfo = S2SMI(dir->i_sb);
565 OBD_ALLOC(buffer, PAGE_SIZE);
567 GOTO(exit, rc = -ENOMEM);
570 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
571 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
578 /*record new_dentry path*/
579 rc = smfs_log_path(dir->i_sb, new_dentry, pbuf, buf_len);
584 KML_BUF_REC_END(buffer, length, pbuf);
586 rc = smfs_pack_rec(pbuf, dentry, dir,
587 new_dir, new_dentry, REINT_RENAME);
592 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
595 OBD_FREE(buffer, PAGE_SIZE);
599 static int smfs_insert_extents_ea(struct inode *inode, size_t from, loff_t num)
601 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
604 if (SMFS_INODE_OVER_WRITE(inode))
607 rc = fsfilt->fs_insert_extents_ea(inode, OFF2BLKS(from, inode),
608 SIZE2BLKS(num, inode));
612 static int smfs_remove_extents_ea(struct inode *inode, size_t from, loff_t num)
614 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
617 rc = fsfilt->fs_remove_extents_ea(inode, OFF2BLKS(from, inode),
618 SIZE2BLKS(num, inode));
623 static int smfs_remove_all_extents_ea(struct inode *inode)
625 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
628 rc = fsfilt->fs_remove_extents_ea(inode, 0, 0xffffffff);
631 static int smfs_init_extents_ea(struct inode *inode)
633 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
636 rc = fsfilt->fs_init_extents_ea(inode);
640 static int smfs_set_dirty_flags(struct inode *inode, int flags)
642 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
646 if (SMFS_INODE_OVER_WRITE(inode))
648 /*FIXME later, the blocks needed in journal here will be recalculated*/
649 handle = smfs_trans_start(inode, FSFILT_OP_SETATTR, NULL);
650 if (IS_ERR(handle)) {
651 CERROR("smfs_set_dirty_flag:no space for transaction\n");
654 if ((!SMFS_INODE_DIRTY_WRITE(inode) && (!SMFS_INODE_OVER_WRITE(inode))) ||
655 ((flags == SMFS_OVER_WRITE) && (SMFS_INODE_DIRTY_WRITE(inode)))) {
656 rc = fsfilt->fs_set_xattr(inode, handle, REINT_EXTENTS_FLAGS,
657 &flags, sizeof(int));
661 if (flags == SMFS_OVER_WRITE)
662 SMFS_SET_INODE_OVER_WRITE(inode);
664 SMFS_SET_INODE_DIRTY_WRITE(inode);
666 smfs_trans_commit(inode, handle, 0);
670 int smfs_post_rec_setattr(struct inode *inode, struct dentry *dentry,
671 void *data1, void *data2)
673 struct smfs_super_info *sinfo;
674 struct iattr *attr = (struct iattr *)data1;
675 char *buffer = NULL, *pbuf;
676 int rc = 0, length = 0, buf_len = 0;
678 sinfo = S2SMI(inode->i_sb);
682 OBD_ALLOC(buffer, PAGE_SIZE);
684 GOTO(exit, rc = -ENOMEM);
687 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
688 rc = smfs_log_path(inode->i_sb, dentry, pbuf, buf_len);
693 KML_BUF_REC_END(buffer, length, pbuf);
695 rc = smfs_pack_rec(pbuf, dentry, inode,
696 data1, data2, REINT_SETATTR);
702 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
704 if (attr && attr->ia_valid & ATTR_SIZE) {
705 smfs_remove_extents_ea(inode, attr->ia_size,
707 if (attr->ia_size == 0)
708 smfs_set_dirty_flags(inode, SMFS_OVER_WRITE);
710 smfs_set_dirty_flags(inode, SMFS_DIRTY_WRITE);
715 OBD_FREE(buffer, PAGE_SIZE);
719 static int all_blocks_present_ea(struct inode *inode)
725 int smfs_post_rec_write(struct inode *dir, struct dentry *dentry, void *data1,
728 struct smfs_super_info *sinfo;
729 char *buffer = NULL, *pbuf;
730 int rc = 0, length = 0, buf_len = 0;
732 if (!SMFS_INODE_OVER_WRITE(dentry->d_inode) &&
733 !SMFS_INODE_DIRTY_WRITE(dentry->d_inode)) {
734 sinfo = S2SMI(dentry->d_inode->i_sb);
738 OBD_ALLOC(buffer, PAGE_SIZE);
740 GOTO(exit, rc = -ENOMEM);
743 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
744 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
749 memcpy(buffer, &rc, sizeof(int));
750 length = rc + sizeof(int);
752 rc = smfs_pack_rec(pbuf, dentry, dir,
753 data1, data2, REINT_WRITE);
759 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
762 rc = smfs_init_extents_ea(dentry->d_inode);
766 if (dentry->d_inode->i_size == 0) {
767 smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE);
770 loff_t off = *((loff_t*)data1);
771 size_t count = *((size_t*)data2);
773 rc = smfs_insert_extents_ea(dentry->d_inode, off, count);
776 if (all_blocks_present_ea(dentry->d_inode)){
777 smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE);
778 smfs_remove_all_extents_ea(dentry->d_inode);
780 smfs_set_dirty_flags(dentry->d_inode, SMFS_DIRTY_WRITE);
785 OBD_FREE(buffer, PAGE_SIZE);
789 typedef int (*post_kml_rec)(struct inode *dir, struct dentry *dentry,
790 void *data1, void *data2);
792 static post_kml_rec smfs_kml_post[HOOK_MAX + 1] = {
793 [HOOK_CREATE] smfs_post_rec_create,
795 [HOOK_LINK] smfs_post_rec_link,
796 [HOOK_UNLINK] smfs_post_rec_unlink,
797 [HOOK_SYMLINK] smfs_post_rec_create,
798 [HOOK_MKDIR] smfs_post_rec_create,
799 [HOOK_RMDIR] smfs_post_rec_unlink,
800 [HOOK_MKNOD] smfs_post_rec_create,
801 [HOOK_RENAME] smfs_post_rec_rename,
802 [HOOK_SETATTR] smfs_post_rec_setattr,
803 [HOOK_WRITE] smfs_post_rec_write,
806 static int smfs_post_kml_rec(struct inode *dir, void *de, void *data1,
809 if (smfs_kml_post[op]) {
810 struct dentry *dentry = (struct dentry *)de;
812 return smfs_kml_post[op](dir, dentry, data1, data2);