1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * lustre/smfs/journal.c
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.
24 #define DEBUG_SUBSYSTEM S_SM
26 #include <linux/kmod.h>
27 #include <linux/init.h>
29 #include <linux/slab.h>
30 #include <linux/string.h>
31 #include <asm/segment.h>
32 #include <asm/uaccess.h>
33 #include <linux/obd_class.h>
34 #include <linux/obd_support.h>
35 #include <linux/lustre_lib.h>
36 #include <linux/lustre_idl.h>
37 #include <linux/lustre_fsfilt.h>
38 #include <linux/lustre_smfs.h>
39 #include <linux/lvfs.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 void *smfs_trans_start(struct inode *inode, int op, void *desc_private)
58 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
60 CDEBUG(D_INFO, "trans start %p\n", fsfilt->fs_start);
62 SMFS_TRANS_OP(inode, op);
64 /* There are some problem here. fs_start in fsfilt is used by lustre
65 * the journal blocks of write rec are not counted in FIXME later */
67 return fsfilt->fs_start(inode, op, desc_private, 0);
71 void smfs_trans_commit(struct inode *inode, void *handle, int force_sync)
73 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
75 CDEBUG(D_INFO, "trans commit %p\n", fsfilt->fs_commit);
77 if (fsfilt->fs_commit)
78 fsfilt->fs_commit(inode, handle, force_sync);
81 /*smfs_path is gotten from intermezzo*/
82 static char* smfs_path(struct dentry *dentry, struct dentry *root, char *buffer,
85 char * end = buffer + buflen;
87 char * buf_end = buffer + buflen;
97 struct dentry * parent;
102 parent = dentry->d_parent;
103 if (dentry == parent)
105 namelen = dentry->d_name.len;
106 buflen -= namelen + 1;
110 memcpy(end, dentry->d_name.name, namelen);
116 while (end != buf_end)
122 static int smfs_log_path(struct super_block *sb,
123 struct dentry *dentry,
127 struct dentry *root=sb->s_root;
128 char *p_name = buffer + sizeof(int);
132 name = smfs_path(dentry, root, p_name, buffer_len - sizeof(int));
133 namelen = cpu_to_le32(strlen(p_name));
134 memcpy(buffer, &namelen, sizeof(int));
136 namelen += sizeof(int);
140 static inline int log_it(char *buffer, void *data, int length)
142 memcpy(buffer, &length, sizeof(int));
143 memcpy(buffer + sizeof(int), data, length);
144 return (sizeof(int) + length);
147 static int smfs_pack_rec (char *buffer, struct dentry *dentry,
148 struct inode *dir, void *data1,
151 smfs_pack_rec_func pack_func;
154 pack_func = smfs_get_rec_pack_type(dir->i_sb);
158 rc = pack_func(buffer, dentry, dir, data1, data2, op);
162 static int smfs_post_rec_create(struct inode *dir,
163 struct dentry *dentry,
167 struct smfs_super_info *sinfo;
168 char *buffer = NULL, *pbuf;
169 int rc = 0, length = 0, buf_len = 0;
171 sinfo = S2SMI(dentry->d_inode->i_sb);
175 OBD_ALLOC(buffer, PAGE_SIZE);
177 GOTO(exit, rc = -ENOMEM);
180 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
181 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
185 KML_BUF_REC_END(buffer, length, pbuf);
187 rc = smfs_pack_rec(pbuf, dentry, dir,
188 data1, data2, REINT_CREATE);
193 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
196 OBD_FREE(buffer, PAGE_SIZE);
201 static int smfs_post_rec_link(struct inode *dir,
202 struct dentry *dentry,
206 struct smfs_super_info *sinfo;
207 struct dentry *old_dentry = (struct dentry *)data1;
208 char *buffer = NULL, *pbuf = NULL;
209 int rc = 0, length = 0, buf_len = 0;
211 sinfo = S2SMI(dir->i_sb);
214 OBD_ALLOC(buffer, PAGE_SIZE);
216 GOTO(exit, rc = -ENOMEM);
219 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
220 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
225 KML_BUF_REC_END(buffer, length, pbuf);
227 rc = smfs_pack_rec(pbuf, dentry, dir, dentry->d_parent,
228 old_dentry->d_parent, REINT_LINK);
233 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
236 OBD_FREE(buffer, PAGE_SIZE);
241 static int smfs_post_rec_unlink(struct inode *dir, struct dentry *dentry,
242 void *data1, void *data2)
244 struct smfs_super_info *sinfo;
245 int mode = *((int*)data1);
246 char *buffer = NULL, *pbuf = NULL;
247 int length = 0, rc = 0, buf_len = 0;
249 sinfo = S2SMI(dentry->d_inode->i_sb);
253 OBD_ALLOC(buffer, PAGE_SIZE);
255 GOTO(exit, rc = -ENOMEM);
258 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
259 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
264 KML_BUF_REC_END(buffer, length, pbuf);
265 rc = smfs_pack_rec(pbuf, dentry, dir,
266 &mode, NULL, REINT_UNLINK);
272 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
275 OBD_FREE(buffer, PAGE_SIZE);
280 static int smfs_post_rec_rename(struct inode *dir,
281 struct dentry *dentry,
285 struct smfs_super_info *sinfo;
286 struct inode *new_dir = (struct inode *)data1;
287 struct dentry *new_dentry = (struct dentry *)data2;
288 char *buffer = NULL, *pbuf = NULL;
289 int rc = 0, length = 0, buf_len = 0;
291 sinfo = S2SMI(dir->i_sb);
295 OBD_ALLOC(buffer, PAGE_SIZE);
297 GOTO(exit, rc = -ENOMEM);
300 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
301 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
308 /*record new_dentry path*/
309 rc = smfs_log_path(dir->i_sb, new_dentry, pbuf, buf_len);
314 KML_BUF_REC_END(buffer, length, pbuf);
316 rc = smfs_pack_rec(pbuf, dentry, dir,
317 new_dir, new_dentry, REINT_RENAME);
322 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
325 OBD_FREE(buffer, PAGE_SIZE);
329 static int smfs_insert_extents_ea(struct inode *inode, size_t from, loff_t num)
331 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
334 if (SMFS_INODE_OVER_WRITE(inode))
337 rc = fsfilt->fs_insert_extents_ea(inode, OFF2BLKS(from, inode),
338 SIZE2BLKS(num, inode));
342 static int smfs_remove_extents_ea(struct inode *inode, size_t from, loff_t num)
344 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
347 rc = fsfilt->fs_remove_extents_ea(inode, OFF2BLKS(from, inode),
348 SIZE2BLKS(num, inode));
353 static int smfs_remove_all_extents_ea(struct inode *inode)
355 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
358 rc = fsfilt->fs_remove_extents_ea(inode, 0, 0xffffffff);
361 static int smfs_init_extents_ea(struct inode *inode)
363 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
366 rc = fsfilt->fs_init_extents_ea(inode);
370 static int smfs_set_dirty_flags(struct inode *inode, int flags)
372 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
376 if (SMFS_INODE_OVER_WRITE(inode))
378 /*FIXME later, the blocks needed in journal here will be recalculated*/
379 handle = smfs_trans_start(inode, FSFILT_OP_SETATTR, NULL);
380 if (IS_ERR(handle)) {
381 CERROR("smfs_set_dirty_flag:no space for transaction\n");
384 if ((!SMFS_INODE_DIRTY_WRITE(inode) && (!SMFS_INODE_OVER_WRITE(inode))) ||
385 ((flags == SMFS_OVER_WRITE) && (SMFS_INODE_DIRTY_WRITE(inode)))) {
386 rc = fsfilt->fs_set_xattr(inode, handle, REINT_EXTENTS_FLAGS,
387 &flags, sizeof(int));
391 if (flags == SMFS_OVER_WRITE)
392 SMFS_SET_INODE_OVER_WRITE(inode);
394 SMFS_SET_INODE_DIRTY_WRITE(inode);
396 smfs_trans_commit(inode, handle, 0);
400 int smfs_post_rec_setattr(struct inode *inode, struct dentry *dentry,
401 void *data1, void *data2)
403 struct smfs_super_info *sinfo;
404 struct iattr *attr = (struct iattr *)data1;
405 char *buffer = NULL, *pbuf;
406 int rc = 0, length = 0, buf_len = 0;
408 sinfo = S2SMI(inode->i_sb);
412 OBD_ALLOC(buffer, PAGE_SIZE);
414 GOTO(exit, rc = -ENOMEM);
417 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
418 rc = smfs_log_path(inode->i_sb, dentry, pbuf, buf_len);
423 KML_BUF_REC_END(buffer, length, pbuf);
425 rc = smfs_pack_rec(pbuf, dentry, inode,
426 data1, data2, REINT_SETATTR);
432 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
434 if (attr && attr->ia_valid & ATTR_SIZE) {
435 smfs_remove_extents_ea(inode, attr->ia_size,
437 if (attr->ia_size == 0)
438 smfs_set_dirty_flags(inode, SMFS_OVER_WRITE);
440 smfs_set_dirty_flags(inode, SMFS_DIRTY_WRITE);
445 OBD_FREE(buffer, PAGE_SIZE);
449 static int all_blocks_present_ea(struct inode *inode)
455 int smfs_post_rec_write(struct inode *dir, struct dentry *dentry,
456 void *data1, void *data2)
458 struct smfs_super_info *sinfo;
459 char *buffer = NULL, *pbuf;
460 int rc = 0, length = 0, buf_len = 0;
462 if (!SMFS_INODE_OVER_WRITE(dentry->d_inode) &&
463 !SMFS_INODE_DIRTY_WRITE(dentry->d_inode)) {
464 sinfo = S2SMI(dentry->d_inode->i_sb);
468 OBD_ALLOC(buffer, PAGE_SIZE);
470 GOTO(exit, rc = -ENOMEM);
473 KML_BUF_REC_INIT(buffer, pbuf, buf_len);
474 rc = smfs_log_path(dir->i_sb, dentry, pbuf, buf_len);
479 memcpy(buffer, &rc, sizeof(int));
480 length = rc + sizeof(int);
482 rc = smfs_pack_rec(pbuf, dentry, dir,
483 data1, data2, REINT_WRITE);
489 rc = smfs_llog_add_rec(sinfo, (void*)buffer, length);
492 rc = smfs_init_extents_ea(dentry->d_inode);
496 if (dentry->d_inode->i_size == 0) {
497 smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE);
500 loff_t off = *((loff_t*)data1);
501 size_t count = *((size_t*)data2);
503 rc = smfs_insert_extents_ea(dentry->d_inode, off, count);
506 if (all_blocks_present_ea(dentry->d_inode)){
507 smfs_set_dirty_flags(dentry->d_inode, SMFS_OVER_WRITE);
508 smfs_remove_all_extents_ea(dentry->d_inode);
510 smfs_set_dirty_flags(dentry->d_inode, SMFS_DIRTY_WRITE);
515 OBD_FREE(buffer, PAGE_SIZE);
519 typedef int (*post_kml_rec)(struct inode *dir, struct dentry *dentry,
520 void *data1, void *data2);
522 static post_kml_rec smfs_kml_post[REINT_MAX + 1] = {
523 [REINT_SETATTR] smfs_post_rec_setattr,
524 [REINT_CREATE] smfs_post_rec_create,
525 [REINT_LINK] smfs_post_rec_link,
526 [REINT_UNLINK] smfs_post_rec_unlink,
527 [REINT_RENAME] smfs_post_rec_rename,
528 [REINT_WRITE] smfs_post_rec_write,
531 int smfs_post_kml_rec(struct inode *dir, struct dentry *dst_dentry,
532 void *data1, void *data2, int op)
534 return smfs_kml_post[op](dir, dst_dentry, data1, data2);