1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2004 Cluster File Systems, Inc.
6 * This file is part of Lustre, http://www.lustre.org.
8 * Lustre is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU General Public
10 * License as published by the Free Software Foundation.
12 * Lustre is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Lustre; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 # define EXPORT_SYMTAB
26 #define DEBUG_SUBSYSTEM S_FILTER
28 #include <linux/version.h>
30 #include <asm/unistd.h>
31 #include <linux/jbd.h>
32 #include <linux/slab.h>
33 #include <linux/pagemap.h>
34 #include <linux/quotaops.h>
35 #include <linux/version.h>
36 #include <linux/kp30.h>
37 #include <linux/lustre_fsfilt.h>
38 #include <linux/obd.h>
39 #include <linux/obd_class.h>
40 #include <linux/module.h>
41 #include <linux/init.h>
42 #include <linux/lustre_compat25.h>
43 #include <linux/lvfs.h>
44 #include <linux/lustre_smfs.h>
45 #include "lvfs_internal.h"
47 #include <linux/obd.h>
48 #include <linux/lustre_lib.h>
50 int lookup_by_path(char *path, int flags, struct nameidata *nd)
52 struct dentry *dentry = NULL;
55 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
56 if (path_init(path, flags, nd)) {
58 if (path_lookup(path, flags, nd)) {
60 rc = path_walk(path, nd);
68 if (!dentry->d_inode || is_bad_inode(dentry->d_inode) ||
69 (!S_ISDIR(dentry->d_inode->i_mode))) {
76 struct dentry *lookup_create(struct nameidata *nd, int is_dir)
78 struct dentry *dentry;
80 dentry = ERR_PTR(-EEXIST);
81 if (nd->last_type != LAST_NORM)
83 dentry = lookup_hash(&nd->last, nd->dentry);
86 if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
91 dentry = ERR_PTR(-ENOENT);
96 static int lvfs_reint_create(struct super_block *sb, struct reint_record *r_rec)
98 struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
99 char *path = r_rec->name.path_name;
100 int type = r_rec->u_rec.ur_iattr.ia_mode & S_IFMT;
102 struct dentry *dparent = NULL;
103 struct dentry *dentry = NULL;
104 struct inode *dir = NULL;
106 int rc = 0, created = 0, err = 0;
109 rc = lookup_by_path(path, LOOKUP_PARENT, &nd);
115 down(&dparent->d_inode->i_sem);
116 /*create a new dentry*/
117 dentry = lookup_create(&nd, 0);
118 dir = dparent->d_inode;
120 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
121 SMFS_CLEAN_INODE_REC(dir);
125 handle = fsfilt->fs_start(dir, FSFILT_OP_CREATE, NULL, 0);
127 GOTO(cleanup, rc = PTR_ERR(handle));
128 rc = ll_vfs_create(dir, dentry, r_rec->u_rec.ur_iattr.ia_mode,
132 handle = fsfilt->fs_start(dir, FSFILT_OP_MKDIR, NULL, 0);
134 GOTO(cleanup, rc = PTR_ERR(handle));
135 rc = vfs_mkdir(dir, dentry, r_rec->u_rec.ur_iattr.ia_mode);
138 char *new_path = r_rec->u.re_name.path_name;
139 handle = fsfilt->fs_start(dir, FSFILT_OP_SYMLINK, NULL, 0);
141 GOTO(cleanup, rc = PTR_ERR(handle));
142 rc = vfs_symlink(dir, dentry, new_path);
149 int rdev = r_rec->u_rec.ur_rdev;
150 handle = fsfilt->fs_start(dir, FSFILT_OP_MKNOD, NULL, 0);
152 GOTO(cleanup, (handle = NULL, rc = PTR_ERR(handle)));
153 rc = vfs_mknod(dir, dentry, r_rec->u_rec.ur_iattr.ia_mode,
158 CERROR("Error type %d in create\n", type);
164 CERROR("Error for creating mkdir %s\n", path);
171 LTIME_S(iattr.ia_atime) =
172 LTIME_S(r_rec->u_rec.ur_iattr.ia_atime);
173 LTIME_S(iattr.ia_ctime) =
174 LTIME_S(r_rec->u_rec.ur_iattr.ia_ctime);
175 LTIME_S(iattr.ia_mtime) =
176 LTIME_S(r_rec->u_rec.ur_iattr.ia_mtime);
178 iattr.ia_uid = r_rec->u_rec.ur_fsuid;
179 if (dir->i_mode & S_ISGID)
180 iattr.ia_gid = dir->i_gid;
182 iattr.ia_gid = r_rec->u_rec.ur_fsgid;
183 iattr.ia_valid = ATTR_UID | ATTR_GID | ATTR_ATIME |
184 ATTR_MTIME | ATTR_CTIME;
186 rc = fsfilt->fs_setattr(dentry, handle, &iattr, 0);
188 CERROR("error on child setattr: rc = %d\n", rc);
192 iattr.ia_valid = ATTR_MTIME | ATTR_CTIME;
193 rc = fsfilt->fs_setattr(dparent, handle, &iattr, 0);
195 CERROR("error on parent setattr: rc = %d\n", rc);
201 /* Destroy the file we just created. This should not need
202 * extra journal credits, as we have already modified all of
203 * the blocks needed in order to create the file in the first
208 err = vfs_rmdir(dir, dentry);
210 CERROR("rmdir in error path: %d\n", err);
213 err = vfs_unlink(dir, dentry);
215 CERROR("unlink in error path: %d\n", err);
222 rc = fsfilt->fs_commit(dentry->d_inode, handle, 0);
224 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
225 SMFS_SET_INODE_REC(dir);
226 up(&dparent->d_inode->i_sem);
234 static int lvfs_reint_link(struct super_block *sb, struct reint_record *r_rec)
236 struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
237 char *old_path = r_rec->name.path_name;
238 char *new_path = r_rec->u.re_name.path_name;
239 struct nameidata old_nd;
240 struct nameidata new_nd;
241 struct dentry *old_dparent;
242 struct dentry *new_dparent;
243 struct dentry *old_dentry = NULL;
244 struct dentry *new_dentry = NULL;
246 struct inode *dir = NULL;
250 /*get parent dentry*/
251 rc = lookup_by_path(new_path, LOOKUP_PARENT, &new_nd);
255 new_dparent = new_nd.dentry;
257 dir = new_dparent->d_inode;
259 new_dentry = lookup_create(&new_nd, 0);
261 rc = lookup_by_path(old_path, LOOKUP_PARENT, &old_nd);
263 path_release(&new_nd);
266 old_dparent = old_nd.dentry;
267 old_dentry = lookup_one_len(old_nd.last.name, old_dparent,
270 if (!old_dentry || !old_dentry->d_inode ||
271 is_bad_inode(old_dentry->d_inode))
272 GOTO(cleanup, rc = -ENODEV);
273 if (dir->i_rdev != old_dentry->d_inode->i_rdev)
274 GOTO(cleanup, rc = -EINVAL);
276 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
277 SMFS_CLEAN_INODE_REC(dir);
279 handle = fsfilt->fs_start(dir, FSFILT_OP_LINK, NULL, 0);
281 GOTO(cleanup, rc = PTR_ERR(handle));
283 rc = vfs_link(old_dentry, dir, new_dentry);
285 CERROR("replay error: vfs_link error rc=%d", rc);
290 rc = fsfilt->fs_commit(dir, handle, 0);
291 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
292 SMFS_SET_INODE_REC(dir);
297 path_release(&new_nd);
298 path_release(&old_nd);
302 static int lvfs_reint_unlink(struct super_block *sb, struct reint_record *r_rec)
304 struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
305 int type = r_rec->u_rec.ur_iattr.ia_mode & S_IFMT;
306 char *path = r_rec->name.path_name;
308 struct dentry *dparent = NULL;
309 struct dentry *dentry = NULL;
310 struct inode *dir = NULL;
315 rc = lookup_by_path(path, LOOKUP_PARENT, &nd);
321 dir = dparent->d_inode;
323 dentry = lookup_one_len(nd.last.name, dparent, nd.last.len);
324 if (!dentry || !dentry->d_inode || is_bad_inode(dentry->d_inode))
325 GOTO(cleanup, rc = -ENODEV);
327 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
328 SMFS_CLEAN_INODE_REC(dir);
330 handle = fsfilt->fs_start(dir, FSFILT_OP_UNLINK, NULL, 0);
333 GOTO(cleanup, rc = PTR_ERR(handle));
337 rc = vfs_rmdir(dir, dentry);
339 CERROR("rmdir in error path: %d\n", rc);
342 rc = vfs_unlink(dir, dentry);
344 CERROR("unlink in error path: %d\n", rc);
348 /*time attr of dir inode*/
349 struct iattr *iattr = &r_rec->u_rec.ur_pattr;
351 iattr->ia_valid = ATTR_MTIME | ATTR_CTIME;
352 rc = fsfilt->fs_setattr(dparent, handle, iattr, 0);
354 CERROR("error on parent setattr: rc = %d\n", rc);
360 fsfilt->fs_commit(dir, handle, 0);
361 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
362 SMFS_SET_INODE_REC(dir);
369 static int lvfs_reint_rename(struct super_block *sb, struct reint_record *r_rec)
371 struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
372 char *path = r_rec->name.path_name;
373 char *new_path = r_rec->u.re_name.path_name;
374 struct nameidata nd, new_nd;
375 struct dentry *dparent = NULL;
376 struct dentry *new_dparent = NULL;
377 struct dentry *dentry = NULL;
378 struct dentry *new_dentry = NULL;
379 struct inode *dir = NULL;
380 struct inode *new_dir = NULL;
385 rc = lookup_by_path(path, LOOKUP_PARENT, &nd);
390 dir = dparent->d_inode;
391 dentry = lookup_one_len(nd.last.name, dparent, nd.last.len);
393 if (!dentry || !dentry->d_inode || is_bad_inode(dentry->d_inode)) {
397 rc = lookup_by_path(new_path, LOOKUP_PARENT, &new_nd);
400 path_release(&new_nd);
403 new_dparent = new_nd.dentry;
404 new_dir = new_dparent->d_inode;
405 new_dentry = lookup_create(&new_nd, 0);
407 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
408 SMFS_CLEAN_INODE_REC(dir);
410 handle = fsfilt->fs_start(dir, FSFILT_OP_RENAME, NULL, 0);
412 GOTO(cleanup, rc = PTR_ERR(handle));
414 rc = vfs_rename(dir, dentry, new_dir, new_dentry);
416 CERROR("unlink in error path: %d\n", rc);
419 /*restore time attr of dir inode*/
420 struct iattr *iattr = &r_rec->u_rec.ur_pattr;
422 iattr->ia_valid = ATTR_MTIME | ATTR_CTIME;
423 rc = fsfilt->fs_setattr(dparent, handle, iattr, 0);
425 CERROR("error on parent setattr: rc = %d\n", rc);
428 rc = fsfilt->fs_setattr(new_dparent, handle, iattr, 0);
430 CERROR("error on parent setattr: rc = %d\n", rc);
436 rc = fsfilt->fs_commit(dir, handle, 0);
437 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
438 SMFS_SET_INODE_REC(dir);
444 path_release(&new_nd);
448 static int lvfs_reint_setattr(struct super_block *sb,
449 struct reint_record *r_rec)
451 struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
452 char *path = r_rec->name.path_name;
454 struct dentry *dparent = NULL;
455 struct dentry *dentry = NULL;
456 struct inode *dir = NULL;
461 rc = lookup_by_path(path, LOOKUP_PARENT, &nd);
466 dir = dparent->d_inode;
467 dentry = lookup_one_len(nd.last.name, dparent, nd.last.len);
469 if (!dentry || !dentry->d_inode || is_bad_inode(dentry->d_inode)) {
473 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
474 SMFS_CLEAN_INODE_REC(dir);
475 handle = fsfilt->fs_start(dir, FSFILT_OP_SETATTR, NULL, 0);
477 GOTO(cleanup, rc = PTR_ERR(handle));
478 rc = fsfilt->fs_setattr(dentry, handle, &r_rec->u_rec.ur_pattr, 0);
481 fsfilt->fs_commit(dir, handle, 0);
482 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
483 SMFS_SET_INODE_REC(dir);
490 static int lvfs_reint_close(struct super_block *sb, struct reint_record *r_rec)
492 struct fsfilt_operations *fsfilt = S2SMI(sb)->sm_fsfilt;
493 char *path = r_rec->name.path_name;
495 struct dentry *dparent = NULL;
496 struct dentry *dentry = NULL;
497 struct inode *dir = NULL;
499 struct iattr *iattr = &r_rec->u_rec.ur_iattr;
503 rc = lookup_by_path(path, LOOKUP_PARENT, &nd);
508 dir = dparent->d_inode;
509 dentry = lookup_one_len(nd.last.name, dparent, nd.last.len);
511 if (!dentry || !dentry->d_inode || is_bad_inode(dentry->d_inode)) {
515 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
516 SMFS_CLEAN_INODE_REC(dir);
517 handle = fsfilt->fs_start(dir, FSFILT_OP_CREATE, NULL, 0);
519 GOTO(cleanup, rc = PTR_ERR(handle));
521 iattr->ia_valid = ATTR_MTIME | ATTR_CTIME | ATTR_SIZE;
522 rc = fsfilt->fs_setattr(dentry, handle, iattr, 0);
524 CERROR("error on parent setattr: rc = %d\n", rc);
529 fsfilt->fs_commit(dir, handle, 0);
530 if (!SMFS_DO_WRITE_KML(r_rec->u_rec.ur_flags))
531 SMFS_SET_INODE_REC(dir);
538 typedef int (*lvfs_reinter)(struct super_block *sb, struct reint_record *);
539 static lvfs_reinter reinters[REINT_MAX + 1] = {
540 [REINT_SETATTR] lvfs_reint_setattr,
541 [REINT_CREATE] lvfs_reint_create,
542 [REINT_LINK] lvfs_reint_link,
543 [REINT_UNLINK] lvfs_reint_unlink,
544 [REINT_RENAME] lvfs_reint_rename,
545 [REINT_CLOSE] lvfs_reint_close,
547 int lvfs_reint(struct super_block *sb, void *r_rec)
549 return reinters[((struct reint_record*)r_rec)->u_rec.ur_opcode](sb,
550 (struct reint_record *)r_rec);
553 EXPORT_SYMBOL(lvfs_reint);