1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
9 #define DEBUG_SUBSYSTEM S_FILTER
11 #include <linux/version.h>
13 #include <asm/unistd.h>
14 #include <linux/jbd.h>
15 #include <linux/slab.h>
16 #include <linux/pagemap.h>
17 #include <linux/quotaops.h>
18 #include <linux/version.h>
19 #include <linux/kp30.h>
20 #include <linux/lustre_fsfilt.h>
21 #include <linux/obd.h>
22 #include <linux/obd_class.h>
23 #include <linux/module.h>
24 #include <linux/init.h>
25 #include <linux/lustre_compat25.h>
26 #include <linux/lvfs.h>
27 #include <linux/lustre_smfs.h>
28 #include "lvfs_internal.h"
30 #include <linux/obd.h>
31 #include <linux/lustre_lib.h>
34 struct dentry *lookup_create(struct nameidata *nd, int is_dir)
36 struct dentry *dentry;
38 dentry = ERR_PTR(-EEXIST);
39 if (nd->last_type != LAST_NORM)
41 dentry = lookup_hash(&nd->last, nd->dentry);
44 if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
49 dentry = ERR_PTR(-ENOENT);
54 int lookup_by_path(char *path, int flags, struct nameidata *nd)
56 struct dentry *dentry = NULL;
59 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
60 if (path_init(path, flags, nd)) {
62 if (path_lookup(path, flags, nd)) {
64 rc = path_walk(path, nd);
72 if (!dentry->d_inode || is_bad_inode(dentry->d_inode) ||
73 (!S_ISDIR(dentry->d_inode->i_mode))) {
80 static int lvfs_reint_create(struct super_block *sb,
81 struct reint_record *r_rec)
83 struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
84 char *path = r_rec->rec_data1;
85 int type = r_rec->u_rec.ur_iattr.ia_mode & S_IFMT;
87 struct dentry *dparent = NULL;
88 struct dentry *dentry = NULL;
89 struct inode *dir = NULL;
91 int rc = 0, created = 0, err = 0;
93 rc = lookup_by_path(path, LOOKUP_PARENT, &nd);
99 down(&dparent->d_inode->i_sem);
100 /*create a new dentry*/
101 dentry = lookup_create(&nd, 0);
102 dir = dparent->d_inode;
104 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
105 SMFS_CLEAN_INODE_REC(dir);
109 handle = fsfilt->fs_start(dir, FSFILT_OP_CREATE, NULL, 0);
111 GOTO(cleanup, rc = PTR_ERR(handle));
112 rc = ll_vfs_create(dir, dentry, r_rec->u_rec.ur_iattr.ia_mode,
116 handle = fsfilt->fs_start(dir, FSFILT_OP_MKDIR, NULL, 0);
118 GOTO(cleanup, rc = PTR_ERR(handle));
119 rc = vfs_mkdir(dir, dentry, r_rec->u_rec.ur_iattr.ia_mode);
122 char *new_path = r_rec->rec_data2;
123 handle = fsfilt->fs_start(dir, FSFILT_OP_SYMLINK, NULL, 0);
125 GOTO(cleanup, rc = PTR_ERR(handle));
126 rc = vfs_symlink(dir, dentry, new_path);
133 int rdev = r_rec->u_rec.ur_rdev;
134 handle = fsfilt->fs_start(dir, FSFILT_OP_MKNOD, NULL, 0);
136 GOTO(cleanup, (handle = NULL, rc = PTR_ERR(handle)));
137 rc = vfs_mknod(dir, dentry, r_rec->u_rec.ur_iattr.ia_mode,
142 CERROR("Error type %d in create\n", type);
148 CERROR("Error for creating mkdir %s\n", path);
155 LTIME_S(iattr.ia_atime) = LTIME_S(r_rec->u_rec.ur_iattr.ia_atime);
156 LTIME_S(iattr.ia_ctime) = LTIME_S(r_rec->u_rec.ur_iattr.ia_ctime);
157 LTIME_S(iattr.ia_mtime) = LTIME_S(r_rec->u_rec.ur_iattr.ia_mtime);
159 iattr.ia_uid = r_rec->u_rec.ur_fsuid;
160 if (dir->i_mode & S_ISGID)
161 iattr.ia_gid = dir->i_gid;
163 iattr.ia_gid = r_rec->u_rec.ur_fsgid;
164 iattr.ia_valid = ATTR_UID | ATTR_GID | ATTR_ATIME |
165 ATTR_MTIME | ATTR_CTIME;
167 rc = fsfilt->fs_setattr(dentry, handle, &iattr, 0);
169 CERROR("error on child setattr: rc = %d\n", rc);
173 iattr.ia_valid = ATTR_MTIME | ATTR_CTIME;
174 rc = fsfilt->fs_setattr(dparent, handle, &iattr, 0);
176 CERROR("error on parent setattr: rc = %d\n", rc);
182 /* Destroy the file we just created. This should not need
183 * extra journal credits, as we have already modified all of
184 * the blocks needed in order to create the file in the first
189 err = vfs_rmdir(dir, dentry);
191 CERROR("rmdir in error path: %d\n", err);
194 err = vfs_unlink(dir, dentry);
196 CERROR("unlink in error path: %d\n", err);
203 rc = fsfilt->fs_commit(dentry->d_inode, handle, 0);
205 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
206 SMFS_SET_INODE_REC(dir);
207 up(&dparent->d_inode->i_sem);
215 static int lvfs_reint_link(struct super_block *sb,
216 struct reint_record *r_rec)
218 struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
219 char *old_path = r_rec->rec_data1;
220 char *new_path = r_rec->rec_data2;
221 struct nameidata old_nd;
222 struct nameidata new_nd;
223 struct dentry *old_dparent;
224 struct dentry *new_dparent;
225 struct dentry *old_dentry = NULL;
226 struct dentry *new_dentry = NULL;
228 struct inode *dir = NULL;
231 /*get parent dentry*/
232 rc = lookup_by_path(new_path, LOOKUP_PARENT, &new_nd);
236 new_dparent = new_nd.dentry;
238 dir = new_dparent->d_inode;
240 new_dentry = lookup_create(&new_nd, 0);
242 rc = lookup_by_path(old_path, LOOKUP_PARENT, &old_nd);
244 path_release(&new_nd);
247 old_dparent = old_nd.dentry;
248 old_dentry = lookup_one_len(old_nd.last.name, old_dparent,
251 if (! old_dentry || !old_dentry->d_inode
252 || is_bad_inode(old_dentry->d_inode)) {
253 GOTO(cleanup, rc = -ENODEV);
255 if (dir->i_rdev != old_dentry->d_inode->i_rdev) {
256 GOTO(cleanup, rc = -EINVAL);
259 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
260 SMFS_CLEAN_INODE_REC(dir);
262 handle = fsfilt->fs_start(dir, FSFILT_OP_LINK, NULL, 0);
264 GOTO(cleanup, rc = PTR_ERR(handle));
266 rc = vfs_link(old_dentry, dir, new_dentry);
268 CERROR("replay error: vfs_link error rc=%d", rc);
273 rc = fsfilt->fs_commit(dir, handle, 0);
275 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
276 SMFS_SET_INODE_REC(dir);
281 path_release(&new_nd);
282 path_release(&old_nd);
285 static int lvfs_reint_unlink(struct super_block *sb,
286 struct reint_record *r_rec)
288 struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
289 int type = r_rec->u_rec.ur_iattr.ia_mode & S_IFMT;
290 char *path = r_rec->rec_data1;
292 struct dentry *dparent = NULL;
293 struct dentry *dentry = NULL;
294 struct inode *dir = NULL;
298 rc = lookup_by_path(path, LOOKUP_PARENT, &nd);
304 dir = dparent->d_inode;
306 dentry = lookup_one_len(nd.last.name, dparent,
308 if (! dentry || !dentry->d_inode
309 || is_bad_inode(dentry->d_inode)) {
310 GOTO(cleanup, rc = -ENODEV);
313 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
314 SMFS_CLEAN_INODE_REC(dir);
316 handle = fsfilt->fs_start(dir, FSFILT_OP_UNLINK, NULL, 0);
319 GOTO(cleanup, rc = PTR_ERR(handle));
323 rc = vfs_rmdir(dir, dentry);
325 CERROR("rmdir in error path: %d\n", rc);
328 rc = vfs_unlink(dir, dentry);
330 CERROR("unlink in error path: %d\n", rc);
334 /*time attr of dir inode*/
335 struct iattr *iattr = &r_rec->u_rec.ur_pattr;
337 iattr->ia_valid = ATTR_MTIME | ATTR_CTIME;
338 rc = fsfilt->fs_setattr(dparent, handle, iattr, 0);
340 CERROR("error on parent setattr: rc = %d\n", rc);
346 fsfilt->fs_commit(dir, handle, 0);
347 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
348 SMFS_SET_INODE_REC(dir);
355 static int lvfs_reint_rename(struct super_block *sb,
356 struct reint_record *r_rec)
358 struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
359 char *path = r_rec->rec_data1;
360 char *new_path = r_rec->rec_data2;
362 struct nameidata new_nd;
363 struct dentry *dparent = NULL;
364 struct dentry *new_dparent = NULL;
365 struct dentry *dentry = NULL;
366 struct dentry *new_dentry = NULL;
367 struct inode *dir = NULL;
368 struct inode *new_dir = NULL;
372 rc = lookup_by_path(path, LOOKUP_PARENT, &nd);
377 dir = dparent->d_inode;
378 dentry = lookup_one_len(nd.last.name, dparent, nd.last.len);
380 if (!dentry || !dentry->d_inode
381 || is_bad_inode(dentry->d_inode)) {
385 rc = lookup_by_path(new_path, LOOKUP_PARENT, &new_nd);
388 path_release(&new_nd);
391 new_dparent = new_nd.dentry;
392 new_dir = new_dparent->d_inode;
393 new_dentry = lookup_create(&new_nd, 0);
395 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
396 SMFS_CLEAN_INODE_REC(dir);
398 handle = fsfilt->fs_start(dir, FSFILT_OP_RENAME, NULL, 0);
400 GOTO(cleanup, rc = PTR_ERR(handle));
402 rc = vfs_rename(dir, dentry, new_dir, new_dentry);
404 CERROR("unlink in error path: %d\n", rc);
407 /*restore time attr of dir inode*/
408 struct iattr *iattr = &r_rec->u_rec.ur_pattr;
410 iattr->ia_valid = ATTR_MTIME | ATTR_CTIME;
411 rc = fsfilt->fs_setattr(dparent, handle, iattr, 0);
413 CERROR("error on parent setattr: rc = %d\n", rc);
416 rc = fsfilt->fs_setattr(new_dparent, handle, iattr, 0);
418 CERROR("error on parent setattr: rc = %d\n", rc);
424 rc = fsfilt->fs_commit(dir, handle, 0);
425 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
426 SMFS_SET_INODE_REC(dir);
432 path_release(&new_nd);
436 static int lvfs_reint_setattr(struct super_block *sb,
437 struct reint_record *r_rec)
439 struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
440 char *path = r_rec->rec_data1;
442 struct dentry *dparent = NULL;
443 struct dentry *dentry = NULL;
444 struct inode *dir = NULL;
448 rc = lookup_by_path(path, LOOKUP_PARENT, &nd);
453 dir = dparent->d_inode;
454 dentry = lookup_one_len(nd.last.name, dparent, nd.last.len);
456 if (!dentry || !dentry->d_inode
457 || is_bad_inode(dentry->d_inode)) {
461 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
462 SMFS_CLEAN_INODE_REC(dir);
463 handle = fsfilt->fs_start(dir, FSFILT_OP_SETATTR, NULL, 0);
465 GOTO(cleanup, rc = PTR_ERR(handle));
466 rc = fsfilt->fs_setattr(dentry, handle, &r_rec->u_rec.ur_pattr, 0);
469 fsfilt->fs_commit(dir, handle, 0);
470 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
471 SMFS_SET_INODE_REC(dir);
477 static int lvfs_reint_close(struct super_block *sb,
478 struct reint_record *r_rec)
480 struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
481 char *path = r_rec->rec_data1;
483 struct dentry *dparent = NULL;
484 struct dentry *dentry = NULL;
485 struct inode *dir = NULL;
487 struct iattr *iattr = &r_rec->u_rec.ur_iattr;
490 rc = lookup_by_path(path, LOOKUP_PARENT, &nd);
495 dir = dparent->d_inode;
496 dentry = lookup_one_len(nd.last.name, dparent, nd.last.len);
498 if (!dentry || !dentry->d_inode
499 || is_bad_inode(dentry->d_inode)) {
503 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
504 SMFS_CLEAN_INODE_REC(dir);
505 handle = fsfilt->fs_start(dir, FSFILT_OP_CREATE, NULL, 0);
507 GOTO(cleanup, rc = PTR_ERR(handle));
508 iattr->ia_valid = ATTR_MTIME | ATTR_CTIME | ATTR_SIZE;
510 rc = fsfilt->fs_setattr(dentry, handle, iattr, 0);
512 CERROR("error on parent setattr: rc = %d\n", rc);
517 fsfilt->fs_commit(dir, handle, 0);
518 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
519 SMFS_SET_INODE_REC(dir);
526 typedef int (*lvfs_reinter)(struct super_block *sb, struct reint_record *);
527 static lvfs_reinter reinters[REINT_MAX + 1] = {
528 [REINT_SETATTR] lvfs_reint_setattr,
529 [REINT_CREATE] lvfs_reint_create,
530 [REINT_LINK] lvfs_reint_link,
531 [REINT_UNLINK] lvfs_reint_unlink,
532 [REINT_RENAME] lvfs_reint_rename,
533 [REINT_CLOSE] lvfs_reint_close,
535 int lvfs_reint(struct super_block *sb,
538 return reinters[((struct reint_record*)r_rec)->u_rec.ur_opcode](sb,
539 (struct reint_record *)r_rec);
542 EXPORT_SYMBOL(lvfs_reint);