Whamcloud - gitweb
- more systematic unpacking/packing and handling of update records
[fs/lustre-release.git] / lustre / mds / mds_reint.c
1 /*
2  *  linux/mds/mds_reint.c
3  *  
4  *  Lustre Metadata Server (mds) reintegration routines
5  * 
6  *  Copyright (C) 2002  Cluster File Systems, Inc.
7  *  author: Peter Braam <braam@clusterfs.com>
8  *
9  *  This code is issued under the GNU General Public License.
10  *  See the file COPYING in this distribution
11  *
12  */
13
14 // XXX - add transaction sequence numbers
15
16 #define EXPORT_SYMTAB
17
18 #include <linux/version.h>
19 #include <linux/module.h>
20 #include <linux/fs.h>
21 #include <linux/stat.h>
22 #include <linux/locks.h>
23 #include <linux/ext2_fs.h>
24 #include <linux/quotaops.h>
25 #include <asm/unistd.h>
26 #include <asm/uaccess.h>
27 #include <linux/obd_support.h>
28 #include <linux/obd.h>
29 #include <linux/lustre_lib.h>
30 #include <linux/lustre_idl.h>
31 #include <linux/lustre_mds.h>
32 #include <linux/obd_class.h>
33
34 extern struct mds_request *mds_prep_req(int size, int opcode, int namelen, char *name, int tgtlen, char *tgt);
35
36 static int mds_reint_setattr(struct mds_update_record *rec, struct mds_request *req)
37 {
38         struct vfsmount *mnt;
39         struct dentry *de;
40
41         de = mds_fid2dentry(req->rq_obd, rec->ur_fid1, &mnt);
42         if (IS_ERR(de)) { 
43                 req->rq_rephdr->status = -ESTALE;
44                 return 0;
45         }
46
47         printk("mds_setattr: ino %ld\n", de->d_inode->i_ino);
48         req->rq_rephdr->status = notify_change(de, &rec->ur_iattr);
49
50         dput(de);
51         EXIT;
52         return 0;
53 }
54
55 static int mds_reint_create(struct mds_update_record *rec, 
56                             struct mds_request *req)
57 {
58         struct vfsmount *mnt;
59         int type = rec->ur_mode & S_IFMT;
60         struct dentry *de;
61         struct dentry *dchild; 
62         int rc;
63
64         de = mds_fid2dentry(req->rq_obd, rec->ur_fid1, &mnt);
65         if (IS_ERR(de)) { 
66                 req->rq_rephdr->status = -ESTALE;
67                 return 0;
68         }
69         printk("mds_reint_create: ino %ld\n", de->d_inode->i_ino);
70
71         dchild = lookup_one_len(rec->ur_name, de, rec->ur_namelen);
72         rc = PTR_ERR(dchild);
73         if (IS_ERR(dchild)) { 
74                 printk(__FUNCTION__ "child lookup error %d\n", rc);
75                 dput(de); 
76                 req->rq_rephdr->status = -ESTALE;
77                 return 0;
78         }
79
80         if (dchild->d_inode) {
81                 printk(__FUNCTION__ "child exists (dir %ld, name %s\n", 
82                        de->d_inode->i_ino, rec->ur_name);
83                 dput(de); 
84                 req->rq_rephdr->status = -ESTALE;
85                 return 0;
86         }
87
88         switch (type) {
89         case S_IFREG: { 
90                 rc = vfs_create(de->d_inode, dchild, rec->ur_mode);
91                 break;
92         }
93         case S_IFDIR: { 
94                 rc = vfs_mkdir(de->d_inode, dchild, rec->ur_mode);
95                 break;
96         } 
97         case S_IFCHR:
98         case S_IFBLK:
99         case S_IFIFO:
100         case S_IFSOCK: { 
101                 int rdev = rec->ur_id;
102                 rc = vfs_mknod(de->d_inode, dchild, rec->ur_mode, rdev); 
103                 break;
104         }
105         }
106         req->rq_rephdr->status = rc;
107
108         dput(de);
109         dput(dchild); 
110         EXIT;
111         return 0;
112 }
113
114 typedef int (*mds_reinter)(struct mds_update_record *, struct mds_request*); 
115
116 static mds_reinter  reinters[REINT_MAX+1] = { 
117         [REINT_SETATTR]   mds_reint_setattr, 
118         [REINT_CREATE]   mds_reint_create
119 };
120
121 int mds_reint_rec(struct mds_update_record *rec, struct mds_request *req)
122 {
123         int rc; 
124
125         if (rec->ur_opcode < 0 || rec->ur_opcode > REINT_MAX) { 
126                 printk(__FUNCTION__ "opcode %d not valid\n", 
127                        rec->ur_opcode); 
128                 return -EINVAL;
129         }
130
131         rc = mds_pack_rep(NULL, 0, NULL, 0, &req->rq_rephdr, &req->rq_rep, 
132                           &req->rq_replen, &req->rq_repbuf);
133         if (rc) { 
134                 EXIT;
135                 printk("mds: out of memory\n");
136                 req->rq_status = -ENOMEM;
137                 return -ENOMEM;
138         }
139         req->rq_rephdr->seqno = req->rq_reqhdr->seqno;
140
141         rc = reinters[rec->ur_opcode](rec, req); 
142         return rc;
143
144