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; \
57 static int smfs_llog_process_rec_cb(struct llog_handle *handle,
58 struct llog_rec_hdr *rec, void *data)
61 struct smfs_proc_args *args = (struct smfs_proc_args *)data;
62 struct lvfs_run_ctxt saved;
65 if (!(le32_to_cpu(handle->lgh_hdr->llh_flags) & LLOG_F_IS_PLAIN)) {
66 CERROR("log is not plain\n");
70 if (le32_to_cpu(rec->lrh_type) == LLOG_GEN_REC) {
71 struct llog_cookie cookie;
73 cookie.lgc_lgl = handle->lgh_id;
74 cookie.lgc_index = le32_to_cpu(rec->lrh_index);
76 llog_cancel(handle->lgh_ctxt, 1, &cookie, 0, NULL);
77 RETURN(LLOG_PROC_BREAK);
80 if (le32_to_cpu(rec->lrh_type) != SMFS_UPDATE_REC)
83 rec_buf = (char*) (rec + 1);
85 if (!S2SMI(args->sr_sb)->smsi_ctxt)
86 GOTO(exit, rc = -ENODEV);
88 push_ctxt(&saved, S2SMI(args->sr_sb)->smsi_ctxt, NULL);
90 /*FIXME later should first unpack the rec,
91 * then call lvfs_reint or lvfs_undo
92 * kml rec format has changed lvfs_reint lvfs_undo should
93 * be rewrite FIXME later*/
94 if (SMFS_DO_REINT_REC(args->sr_flags))
95 rc = lvfs_reint(args->sr_sb, rec_buf);
97 rc = lvfs_undo(args->sr_sb, rec_buf);
99 if (!rc && !SMFS_DO_REC_ALL(args->sr_flags)) {
101 if (args->sr_count == 0)
102 rc = LLOG_PROC_BREAK;
104 pop_ctxt(&saved, S2SMI(args->sr_sb)->smsi_ctxt, NULL);
109 static smfs_pack_rec_func smfs_get_rec_pack_type(struct super_block *sb)
112 struct smfs_super_info *smsi = S2SMI(sb);
114 idx = GET_REC_PACK_TYPE_INDEX(smsi->smsi_flags);
115 return smsi->smsi_pack_rec[idx];
119 copy_inode_attr(struct iattr *iattr, struct inode *inode)
121 iattr->ia_mode = inode->i_mode;
122 iattr->ia_uid = inode->i_uid;
123 iattr->ia_gid = inode->i_gid;
124 iattr->ia_atime = inode->i_atime;
125 iattr->ia_ctime = inode->i_ctime;
126 iattr->ia_mtime = inode->i_mtime;
127 iattr->ia_size = inode->i_size;
130 static inline int unpack_rec_data(char **p_buffer, int *size,
131 char *in_data, char *args_data)
138 args_len = strlen(args_data);
140 *size = *((int*)(in_data));
141 rc = *size + sizeof(int);
143 OBD_ALLOC(*p_buffer, *size + args_len + 1);
147 /* first copy reint dir. */
149 memcpy(*p_buffer, args_data, args_len);
151 /* then copy the node name. */
152 memcpy(*p_buffer + args_len,
153 (in_data + sizeof(int)), *size);
160 int smfs_rec_unpack(struct smfs_proc_args *args, char *record,
161 char **pbuf, int *opcode)
163 int offset = *(int *)(record);
164 char *tmp = record + offset + sizeof(int);
166 *opcode = *(int *)tmp;
167 *pbuf = tmp + sizeof(*opcode);
170 EXPORT_SYMBOL(smfs_rec_unpack);
172 int smfs_write_extents(struct inode *dir, struct dentry *dentry,
173 unsigned long from, unsigned long num)
175 return smfs_post_rec_write(dir, dentry, &from, &num);
177 EXPORT_SYMBOL(smfs_write_extents);
179 int smfs_rec_setattr(struct inode *dir, struct dentry *dentry,
182 return smfs_post_rec_setattr(dir, dentry, attr, NULL);
184 EXPORT_SYMBOL(smfs_rec_setattr);
186 int smfs_rec_md(struct inode *inode, void *lmm, int lmm_size)
188 char *set_lmm = NULL;
192 if (!SMFS_DO_REC(S2SMI(inode->i_sb)))
196 OBD_ALLOC(set_lmm, lmm_size + sizeof(lmm_size));
199 memcpy(set_lmm, &lmm_size, sizeof(lmm_size));
200 memcpy(set_lmm + sizeof(lmm_size), lmm, lmm_size);
201 rc = smfs_post_rec_setattr(inode, NULL, NULL, set_lmm);
203 CERROR("Error: Record md for inode %lu rc=%d\n",
208 OBD_FREE(set_lmm, lmm_size + sizeof(lmm_size));
211 EXPORT_SYMBOL(smfs_rec_md);
213 int smfs_rec_precreate(struct dentry *dentry, int *num, struct obdo *oa)
215 return smfs_post_rec_create(dentry->d_inode, dentry, num, oa);
217 EXPORT_SYMBOL(smfs_rec_precreate);
219 int smfs_process_rec(struct super_block *sb,
220 int count, char *dir, int flags)
222 struct llog_ctxt *ctxt;
223 struct llog_handle *loghandle;
224 struct smfs_proc_args args;
228 if (!SMFS_INIT_REC(S2SMI(sb))) {
229 CWARN("Did not start up rec server \n");
233 memset(&args, 0, sizeof(struct smfs_proc_args));
235 args.sr_count = count;
237 args.sr_flags = flags ;
238 ctxt = S2SMI(sb)->smsi_kml_log;
239 loghandle = ctxt->loc_handle;
242 if (SMFS_DO_REINT_REC(flags)) {
243 struct llog_gen_rec *lgr;
245 /* for reint rec, we need insert a gen rec to identify
246 * the end of the rec.*/
247 OBD_ALLOC(lgr, sizeof(*lgr));
250 lgr->lgr_hdr.lrh_len = lgr->lgr_tail.lrt_len = sizeof(*lgr);
251 lgr->lgr_hdr.lrh_type = LLOG_GEN_REC;
252 lgr->lgr_gen = ctxt->loc_gen;
253 rc = llog_add(ctxt, &lgr->lgr_hdr, NULL, NULL, 1,
255 OBD_FREE(lgr, sizeof(*lgr));
260 SET_REC_COUNT_FLAGS(args.sr_flags, SMFS_REC_ALL);
263 if (SMFS_DO_REINT_REC(flags))
264 rc = llog_cat_process(loghandle, ctxt->llog_proc_cb,
267 rc = llog_cat_reverse_process(loghandle,
270 if (rc == LLOG_PROC_BREAK)
276 /*smfs_path is gotten from intermezzo*/
277 static char* smfs_path(struct dentry *dentry, struct dentry *root, char *buffer,
280 char * end = buffer + buflen;
281 char * name = buffer;
282 char * buf_end = buffer + buflen;
292 struct dentry * parent;
297 parent = dentry->d_parent;
298 if (dentry == parent)
300 namelen = dentry->d_name.len;
301 buflen -= namelen + 1;
305 memcpy(end, dentry->d_name.name, namelen);
311 while (end != buf_end)
317 static int smfs_log_path(struct super_block *sb,
318 struct dentry *dentry,
322 struct dentry *root=sb->s_root;
323 char *p_name = buffer + sizeof(int);
329 name = smfs_path(dentry, root, p_name, buffer_len - sizeof(int));
330 namelen = cpu_to_le32(strlen(p_name));
331 memcpy(buffer, &namelen, sizeof(int));
333 namelen += sizeof(int);
337 static inline int log_it(char *buffer, void *data, int length)
339 memcpy(buffer, &length, sizeof(int));
340 memcpy(buffer + sizeof(int), data, length);
341 return (sizeof(int) + length);
344 static int smfs_pack_rec (char *buffer, struct dentry *dentry,
345 struct inode *dir, void *data1,
348 smfs_pack_rec_func pack_func;
350 pack_func = smfs_get_rec_pack_type(dir->i_sb);
353 return pack_func(buffer, dentry, dir, data1, data2, op);
356 int smfs_post_rec_create(struct inode *dir, struct dentry *dentry,
357 void *data1, void *data2)
359 struct smfs_super_info *sinfo;
360 char *buffer = NULL, *pbuf;
361 int rc = 0, length = 0, buf_len = 0;
364 sinfo = S2SMI(dentry->d_inode->i_sb);
368 OBD_ALLOC(buffer, PAGE_SIZE);
370 GOTO(exit, rc = -ENOMEM);
373 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
374 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
378 KML_BUF_REC_END(buffer, length, pbuf);
380 rc = smfs_pack_rec(pbuf, dentry, dir,
381 data1, data2, REINT_CREATE);
386 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
389 OBD_FREE(buffer, PAGE_SIZE);
394 static int smfs_post_rec_link(struct inode *dir, struct dentry *dentry,
395 void *data1, void *data2)
397 struct dentry *new_dentry = (struct dentry *)data1;
398 int rc = 0, length = 0, buf_len = 0;
399 char *buffer = NULL, *pbuf = NULL;
400 struct smfs_super_info *sinfo;
403 sinfo = S2SMI(dir->i_sb);
406 OBD_ALLOC(buffer, PAGE_SIZE);
408 GOTO(exit, rc = -ENOMEM);
411 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
413 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
418 KML_BUF_REC_END(buffer, length, pbuf);
420 rc = smfs_pack_rec(pbuf, dentry, dir, dentry,
421 new_dentry, REINT_LINK);
426 rc = smfs_llog_add_rec(sinfo, (void *)buffer, length);
429 OBD_FREE(buffer, PAGE_SIZE);
434 static int smfs_post_rec_unlink(struct inode *dir, struct dentry *dentry,
435 void *data1, void *data2)
437 struct smfs_super_info *sinfo;
438 int mode = *((int*)data1);
439 char *buffer = NULL, *pbuf = NULL;
440 int length = 0, rc = 0, buf_len = 0;
443 sinfo = S2SMI(dentry->d_inode->i_sb);
447 OBD_ALLOC(buffer, PAGE_SIZE);
449 GOTO(exit, rc = -ENOMEM);
452 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
453 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
458 KML_BUF_REC_END(buffer, length, pbuf);
459 rc = smfs_pack_rec(pbuf, dentry, dir,
460 &mode, NULL, REINT_UNLINK);
466 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
469 OBD_FREE(buffer, PAGE_SIZE);
474 static int smfs_post_rec_rename(struct inode *dir, struct dentry *dentry,
475 void *data1, void *data2)
477 struct smfs_super_info *sinfo;
478 struct inode *new_dir = (struct inode *)data1;
479 struct dentry *new_dentry = (struct dentry *)data2;
480 char *buffer = NULL, *pbuf = NULL;
481 int rc = 0, length = 0, buf_len = 0;
484 sinfo = S2SMI(dir->i_sb);
488 OBD_ALLOC(buffer, PAGE_SIZE);
490 GOTO(exit, rc = -ENOMEM);
493 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
494 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
502 /* record new_dentry path. */
503 rc = smfs_log_path(dir->i_sb, new_dentry, pbuf, buf_len);
508 KML_BUF_REC_END(buffer, length, pbuf);
510 rc = smfs_pack_rec(pbuf, dentry, dir,
511 new_dir, new_dentry, REINT_RENAME);
516 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
519 OBD_FREE(buffer, PAGE_SIZE);
523 static int smfs_insert_extents_ea(struct inode *inode, size_t from, loff_t num)
525 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
529 if (SMFS_INODE_OVER_WRITE(inode))
532 rc = fsfilt->fs_insert_extents_ea(inode, OFF2BLKS(from, inode),
533 SIZE2BLKS(num, inode));
537 static int smfs_remove_extents_ea(struct inode *inode, size_t from, loff_t num)
539 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
543 rc = fsfilt->fs_remove_extents_ea(inode, OFF2BLKS(from, inode),
544 SIZE2BLKS(num, inode));
549 static int smfs_remove_all_extents_ea(struct inode *inode)
551 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
555 rc = fsfilt->fs_remove_extents_ea(inode, 0, 0xffffffff);
558 static int smfs_init_extents_ea(struct inode *inode)
560 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
564 rc = fsfilt->fs_init_extents_ea(inode);
568 static int smfs_set_dirty_flags(struct inode *inode, int flags)
570 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
575 if (SMFS_INODE_OVER_WRITE(inode))
577 /*FIXME later, the blocks needed in journal here will be recalculated*/
578 handle = smfs_trans_start(inode, FSFILT_OP_SETATTR, NULL);
579 if (IS_ERR(handle)) {
580 CERROR("smfs_set_dirty_flag:no space for transaction\n");
583 if ((!SMFS_INODE_DIRTY_WRITE(inode) && (!SMFS_INODE_OVER_WRITE(inode))) ||
584 ((flags == SMFS_OVER_WRITE) && (SMFS_INODE_DIRTY_WRITE(inode)))) {
585 rc = fsfilt->fs_set_xattr(inode, handle, REINT_EXTENTS_FLAGS,
586 &flags, sizeof(int));
590 if (flags == SMFS_OVER_WRITE)
591 SMFS_SET_INODE_OVER_WRITE(inode);
593 SMFS_SET_INODE_DIRTY_WRITE(inode);
595 smfs_trans_commit(inode, handle, 0);
599 int smfs_post_rec_setattr(struct inode *inode, struct dentry *dentry,
600 void *data1, void *data2)
602 struct smfs_super_info *sinfo;
603 struct iattr *attr = (struct iattr *)data1;
604 char *buffer = NULL, *pbuf;
605 int rc = 0, length = 0, buf_len = 0;
608 sinfo = S2SMI(inode->i_sb);
612 OBD_ALLOC(buffer, PAGE_SIZE);
614 GOTO(exit, rc = -ENOMEM);
617 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
618 rc = smfs_log_path(inode->i_sb, dentry, pbuf, buf_len);
623 KML_BUF_REC_END(buffer, length, pbuf);
625 rc = smfs_pack_rec(pbuf, dentry, inode,
626 data1, data2, REINT_SETATTR);
632 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
634 if (attr && attr->ia_valid & ATTR_SIZE) {
635 smfs_remove_extents_ea(inode, attr->ia_size,
637 if (attr->ia_size == 0)
638 smfs_set_dirty_flags(inode, SMFS_OVER_WRITE);
640 smfs_set_dirty_flags(inode, SMFS_DIRTY_WRITE);
645 OBD_FREE(buffer, PAGE_SIZE);
649 static int all_blocks_present_ea(struct inode *inode)
656 int smfs_post_rec_write(struct inode *dir, struct dentry *dentry, void *data1,
659 struct smfs_super_info *sinfo;
660 char *buffer = NULL, *pbuf;
661 int rc = 0, length = 0, buf_len = 0;
664 if (!SMFS_INODE_OVER_WRITE(dentry->d_inode) &&
665 !SMFS_INODE_DIRTY_WRITE(dentry->d_inode)) {
666 sinfo = S2SMI(dentry->d_inode->i_sb);
670 OBD_ALLOC(buffer, PAGE_SIZE);
672 GOTO(exit, rc = -ENOMEM);
675 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
676 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
681 memcpy(buffer, &rc, sizeof(int));
682 length = rc + sizeof(int);
684 rc = smfs_pack_rec(pbuf, dentry, dir,
685 data1, data2, REINT_WRITE);
691 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
694 rc = smfs_init_extents_ea(dentry->d_inode);
698 if (dentry->d_inode->i_size == 0) {
699 smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE);
702 loff_t off = *((loff_t*)data1);
703 size_t count = *((size_t*)data2);
705 rc = smfs_insert_extents_ea(dentry->d_inode, off, count);
708 if (all_blocks_present_ea(dentry->d_inode)){
709 smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE);
710 smfs_remove_all_extents_ea(dentry->d_inode);
712 smfs_set_dirty_flags(dentry->d_inode, SMFS_DIRTY_WRITE);
717 OBD_FREE(buffer, PAGE_SIZE);
723 struct dentry * kml_llog_dir;
726 static int kml_create(struct inode * inode, void *arg)
728 struct hook_msg * msg = arg;
729 return smfs_post_rec_create(inode, msg->dentry, NULL, NULL);
732 static int kml_link(struct inode * inode, void *arg)
734 struct hook_link_msg * msg = arg;
735 return smfs_post_rec_link(inode, msg->dentry, msg->new_dentry, NULL);
738 static int kml_unlink(struct inode * inode, void *arg)
740 struct hook_unlink_msg * msg = arg;
741 return smfs_post_rec_unlink(inode, msg->dentry, &msg->mode, NULL);
744 static int kml_symlink(struct inode * inode, void *arg)
746 struct hook_symlink_msg * msg = arg;
747 return smfs_post_rec_create(inode, msg->dentry, &msg->tgt_len,
751 static int kml_rename(struct inode * inode, void *arg)
753 struct hook_rename_msg * msg = arg;
754 return smfs_post_rec_rename(inode, msg->dentry, msg->new_dir,
758 static int kml_setattr(struct inode * inode, void *arg)
760 struct hook_setattr_msg * msg = arg;
761 return smfs_post_rec_setattr(inode, msg->dentry, msg->attr, NULL);
764 static int kml_write(struct inode * inode, void *arg)
766 struct hook_write_msg * msg = arg;
767 return smfs_post_rec_write(inode, msg->dentry, &msg->count, &msg->pos);
770 typedef int (*post_kml_op)(struct inode * inode, void *msg);
771 static post_kml_op smfs_kml_post[HOOK_MAX] = {
772 [HOOK_CREATE] kml_create,
774 [HOOK_LINK] kml_link,
775 [HOOK_UNLINK] kml_unlink,
776 [HOOK_SYMLINK] kml_symlink,
777 [HOOK_MKDIR] kml_create,
778 [HOOK_RMDIR] kml_unlink,
779 [HOOK_MKNOD] kml_create,
780 [HOOK_RENAME] kml_rename,
781 [HOOK_SETATTR] kml_setattr,
782 [HOOK_WRITE] kml_write,
786 static int smfs_kml_post_op(int code, struct inode * inode,
787 void * msg, int ret, void * priv)
792 CDEBUG(D_INODE,"KML: inode %lu, code: %u\n", inode->i_ino, code);
793 //KML don't handle failed ops
797 if (smfs_kml_post[code]) {
798 rc = smfs_kml_post[code](inode, msg);
805 static int smfs_exit_kml(struct super_block *sb, void * arg, struct kml_priv * priv)
809 smfs_deregister_plugin(sb, SMFS_PLG_KML);
815 static int smfs_trans_kml (struct super_block *sb, void *arg,
816 struct kml_priv * priv)
822 size = 20;//LDISKFS_INDEX_EXTRA_TRANS_BLOCKS+LDISKFS_DATA_TRANS_BLOCKS;
827 static int smfs_start_kml(struct super_block *sb, void *arg,
828 struct kml_priv * kml_p)
831 struct smfs_super_info * smb = S2SMI(sb);
832 struct llog_ctxt **ctxt = &smb->smsi_kml_log;
835 //is plugin already activated
836 if (SMFS_IS(smb->plg_flags, SMFS_PLG_KML))
839 //this will do OBD_ALLOC() for ctxt
840 rc = llog_catalog_setup(ctxt, KML_LOG_NAME, smb->smsi_exp,
841 smb->smsi_ctxt, smb->sm_fsfilt,
843 smb->smsi_objects_dir);
846 CERROR("Failed to initialize kml log list catalog %d\n", rc);
850 (*ctxt)->llog_proc_cb = smfs_llog_process_rec_cb;
852 SMFS_SET(smb->plg_flags, SMFS_PLG_KML);
857 int smfs_stop_kml(struct super_block *sb, void *arg,
858 struct kml_priv * kml_p)
860 struct smfs_super_info * smb = S2SMI(sb);
861 struct llog_ctxt *ctxt = smb->smsi_kml_log;
864 if (!SMFS_IS(smb->plg_flags, SMFS_PLG_KML))
867 SMFS_CLEAR(smb->plg_flags, SMFS_PLG_KML);
869 llog_catalog_cleanup(ctxt);
870 OBD_FREE(ctxt, sizeof(*ctxt));
875 typedef int (*kml_helper)(struct super_block * sb, void *msg, struct kml_priv *);
876 static kml_helper smfs_kml_helpers[PLG_HELPER_MAX] = {
877 [PLG_EXIT] smfs_exit_kml,
878 [PLG_START] smfs_start_kml,
879 [PLG_STOP] smfs_stop_kml,
880 [PLG_TRANS_SIZE] smfs_trans_kml,
881 [PLG_TEST_INODE] NULL,
882 [PLG_SET_INODE] NULL,
885 static int smfs_kml_help_op(int code, struct super_block * sb,
886 void * arg, void * priv)
890 if (smfs_kml_helpers[code])
891 rc = smfs_kml_helpers[code](sb, arg, (struct kml_priv *) priv);
895 int smfs_init_kml(struct super_block *sb)
898 struct smfs_super_info *smb = S2SMI(sb);
899 struct smfs_plugin plg = {
900 .plg_type = SMFS_PLG_KML,
902 .plg_post_op = &smfs_kml_post_op,
903 .plg_helper = &smfs_kml_help_op,
909 rc = ost_rec_pack_init(smb);
913 rc = mds_rec_pack_init(smb);
917 rc = smfs_register_plugin(sb, &plg);