Whamcloud - gitweb
- landed b_hd_mdref (mostly WB cache fixes)
[fs/lustre-release.git] / lustre / smfs / mds_kml.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Lustre filesystem abstraction routines
5  *
6  *  Copyright (C) 2004 Cluster File Systems, Inc.
7  *
8  *   This file is part of Lustre, http://www.lustre.org.
9  *
10  *   Lustre is free software; you can redistribute it and/or
11  *   modify it under the terms of version 2 of the GNU General Public
12  *   License as published by the Free Software Foundation.
13  *
14  *   Lustre is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *   GNU General Public License for more details.
18  *
19  *   You should have received a copy of the GNU General Public License
20  *   along with Lustre; if not, write to the Free Software
21  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 #define DEBUG_SUBSYSTEM S_SM
25
26 #include <linux/kmod.h>
27 #include <linux/init.h>
28 #include <linux/fs.h>
29 #include <linux/slab.h>
30 #include <linux/dcache.h>
31 #include <linux/obd_class.h>
32 #include <linux/obd_support.h>
33 #include <linux/lustre_lib.h>
34 #include <linux/lustre_idl.h>
35 #include <linux/lustre_fsfilt.h>
36 #include <linux/lustre_lite.h>
37 #include <linux/lustre_mds.h>
38 #include <linux/lustre_smfs.h>
39 #include "smfs_internal.h"
40
41 /* get lustre_id from "sid" attribute. */
42 static int mds_rec_get_id(struct inode *inode, struct lustre_id *id)
43 {
44         struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_fsfilt;
45         int rc = 0;
46         ENTRY;
47
48         LASSERT(id != NULL);
49         LASSERT(inode != NULL);
50
51         rc = fsfilt->fs_get_xattr(inode, XATTR_LUSTRE_MDS_SID_EA,
52                                   &id->li_fid, sizeof(id->li_fid));
53         
54         if (rc > 0) {
55                 LASSERT(id_fid(id) != 0);
56                 rc = 0;
57         } else if (rc == 0) {
58                 rc = -ENODATA;
59         }
60         
61         RETURN(rc);
62 }
63
64 static int mds_rec_link_pack(char *buffer, struct dentry *dentry,
65                              struct inode *dir, void *data1, void *data2)
66 {
67         struct dentry *src = (struct dentry *)data1;
68         struct dentry *tgt = (struct dentry *)data2;
69         struct mds_kml_pack_info *mkpi;
70         struct lustre_msg *msg = NULL;
71         struct mdc_op_data *op_data;
72         void *tmp = NULL;
73         int rc = 0;
74         ENTRY;
75
76         OBD_ALLOC(op_data, sizeof(*op_data));
77         if (op_data == NULL)
78                 return -ENOMEM;
79         
80         smfs_prepare_mdc_data(op_data, src->d_inode, dir,
81                               (char *)tgt->d_name.name,
82                               tgt->d_name.len, 0);
83
84         mds_rec_get_id(src->d_inode, &op_data->id1);
85         mds_rec_get_id(dir, &op_data->id2);
86
87         PACK_KML_REC_INIT(buffer, MDS_REINT);
88         mkpi = (struct mds_kml_pack_info *)buffer;
89
90         mkpi->mpi_bufcount = 2;
91         mkpi->mpi_size[0] = sizeof(struct mds_rec_link);
92         mkpi->mpi_size[1] = op_data->namelen + 1;
93
94         /* the mds reint log format is: opcode + mkpi + request  */
95         msg = (struct lustre_msg *)(buffer + sizeof(*mkpi));
96         lustre_init_msg(msg, mkpi->mpi_bufcount, mkpi->mpi_size, NULL);
97
98         tmp = mdc_link_pack(msg, 0, op_data);
99         OBD_FREE(op_data, sizeof(*op_data));
100         mkpi->mpi_total_size = tmp - (void *)msg;
101         rc = mkpi->mpi_total_size + sizeof(*mkpi) + sizeof(int);
102         
103         RETURN(rc);
104 }
105
106 static int mds_rec_setxattr_pack(char *buffer, struct dentry *dentry,
107                                  struct inode *dir, void *data1, void *data2)
108 {
109         struct kml_buffer *kbuf = (struct kml_buffer *)data2;
110         struct mds_rec_setattr *rec = NULL;
111         struct mds_kml_pack_info *mkpi;
112         struct lustre_msg *msg = NULL;
113         struct mdc_op_data *op_data;
114         char *name = (char *)data1;
115         void *tmp = NULL;
116         int rc = 0;
117         ENTRY;
118
119         OBD_ALLOC(op_data, sizeof(*op_data));
120         if (op_data == NULL)
121                 return -ENOMEM;
122         
123         smfs_prepare_mdc_data(op_data, dir, NULL, NULL, 0, 0);
124         mds_rec_get_id(dir, &op_data->id1);
125
126         PACK_KML_REC_INIT(buffer, MDS_REINT);
127         mkpi = (struct mds_kml_pack_info *)buffer;
128
129         mkpi->mpi_bufcount = 3;
130         mkpi->mpi_size[0] = sizeof(struct mds_rec_setattr);
131         mkpi->mpi_size[1] = strlen(name);
132         mkpi->mpi_size[2] = kbuf->buf_size;       
133  
134         msg = (struct lustre_msg *)(buffer + sizeof(*mkpi));
135         lustre_init_msg(msg, mkpi->mpi_bufcount, mkpi->mpi_size, NULL);
136
137         LASSERT(kbuf && name);
138
139         tmp = mdc_setattr_pack(msg, 0, op_data, NULL, name, strlen(name), 
140                                kbuf->buf, kbuf->buf_size, NULL, 0);
141         OBD_FREE(op_data, sizeof(*op_data));
142
143         rec = (struct mds_rec_setattr *)lustre_msg_buf(msg, 0, 0);
144         rec->sa_valid = ATTR_EA_CMOBD;
145         
146         mkpi->mpi_total_size = tmp - (void *)msg;
147         rc = mkpi->mpi_total_size + sizeof(*mkpi) + sizeof(int);
148
149         RETURN(rc);
150 }
151
152 /* FIXME-WANGDI: did not think about EA situation. */
153 static int mds_rec_setattr_pack(char *buffer, struct dentry *dentry,
154                                 struct inode *dir, void *data1, void *data2)
155 {
156         struct iattr *iattr = (struct iattr *)data1;
157         struct mds_rec_setattr *rec = NULL;
158         struct mds_kml_pack_info *mkpi;
159         struct lustre_msg *msg = NULL;
160         struct mdc_op_data *op_data;
161         int rc = 0, ealen = 0;
162         char *ea = NULL;
163         void *tmp = NULL;
164         ENTRY;
165
166         OBD_ALLOC(op_data, sizeof(*op_data));
167         if (op_data == NULL)
168                 return -ENOMEM;
169
170         smfs_prepare_mdc_data(op_data, dir, NULL, NULL, 0, 0);
171         mds_rec_get_id(dir, &op_data->id1);
172
173         PACK_KML_REC_INIT(buffer, MDS_REINT);
174         mkpi = (struct mds_kml_pack_info *)buffer;
175
176         mkpi->mpi_bufcount = 1;
177         mkpi->mpi_size[0] = sizeof(struct mds_rec_setattr);
178         if (data2) {
179                 mkpi->mpi_bufcount++;
180                 mkpi->mpi_size[1] = *(int *)data2;
181                 ealen = *(int *)data2;
182                 ea = data2 + sizeof(ealen);
183         }
184
185         msg = (struct lustre_msg *)(buffer + sizeof(*mkpi));
186         lustre_init_msg(msg, mkpi->mpi_bufcount, mkpi->mpi_size, NULL);
187
188         tmp = mdc_setattr_pack(msg, 0, op_data, iattr, ea, ealen, 
189                                NULL, 0, NULL, 0);
190         OBD_FREE(op_data, sizeof(*op_data));
191
192         /* FIXME-WANGDI: there are maybe some better ways to set the time
193          * attr. */
194         rec = (struct mds_rec_setattr *)lustre_msg_buf(msg, 0, 0);
195         if (rec->sa_valid & ATTR_CTIME)
196                 rec->sa_valid |= ATTR_CTIME_SET;
197         if (rec->sa_valid & ATTR_MTIME)
198                 rec->sa_valid |= ATTR_MTIME_SET;
199         if (rec->sa_valid & ATTR_ATIME)
200                 rec->sa_valid |= ATTR_ATIME_SET;
201
202         mkpi->mpi_total_size = tmp - (void *)msg;
203         rc = mkpi->mpi_total_size + sizeof(*mkpi) + sizeof(int);
204         RETURN(rc);
205 }
206
207 static int mds_rec_create_pack(char *buffer, struct dentry *dentry,
208                                struct inode *dir, void *data1,
209                                void *data2)
210 {
211         struct mds_kml_pack_info *mkpi;
212         struct lustre_msg *msg = NULL;
213         struct dentry_params *param;
214         struct mdc_op_data *op_data;
215         struct mds_rec_create *rec;
216         int rc = 0, tgt_len = 0;
217         void *tmp = NULL;
218         ENTRY;
219         
220         param = (struct dentry_params *)dentry->d_fsdata;
221         OBD_ALLOC(op_data, sizeof(*op_data));
222         if (op_data == NULL)
223                 return -ENOMEM;
224         
225         smfs_prepare_mdc_data(op_data, dir, dentry->d_inode,
226                               (char *)dentry->d_name.name,
227                               dentry->d_name.len, 0);
228
229         mds_rec_get_id(dir, &op_data->id1);
230
231         id_fid(&op_data->id2) = param->p_fid;
232         id_group(&op_data->id2) = param->p_group;
233         
234         PACK_KML_REC_INIT(buffer, MDS_REINT);
235         mkpi = (struct mds_kml_pack_info *)buffer;
236
237         mkpi->mpi_bufcount = 2;
238         mkpi->mpi_size[0] = sizeof(struct mds_rec_create);
239         mkpi->mpi_size[1] = op_data->namelen + 1;
240
241         if (data1 && data2) {
242                 mkpi->mpi_size[2] = *(int *)data2;
243                 mkpi->mpi_bufcount++;
244         }
245
246         /* for symlink, data1 will be the tgt name. */
247         if (data1)
248                 tgt_len = *(int *)data2;
249
250         msg = (struct lustre_msg *)(buffer + sizeof(*mkpi));
251         lustre_init_msg(msg, mkpi->mpi_bufcount, mkpi->mpi_size, NULL);
252
253         tmp = mdc_create_pack(msg, 0, op_data, dentry->d_inode->i_mode,
254                               dentry->d_inode->i_mode, data1, tgt_len);
255
256         rec = (struct mds_rec_create *)lustre_msg_buf(msg, 0, 0);
257         rec->cr_replayid = op_data->id2;
258         rec->cr_flags |= REC_REINT_CREATE; 
259         mkpi->mpi_total_size = tmp - (void *)msg;
260         rc = mkpi->mpi_total_size + sizeof(*mkpi) + sizeof(int);
261         OBD_FREE(op_data, sizeof(*op_data));
262         RETURN(rc);
263 }
264
265 static int mds_rec_unlink_pack(char *buffer, struct dentry *dentry,
266                                struct inode *dir, void *data1,
267                                void *data2)
268 {
269         struct lustre_msg *msg = NULL;
270         struct mds_kml_pack_info *mkpi;
271         struct mdc_op_data *op_data;
272         int mode = *(int*)data1;
273         void *tmp = NULL;
274         int rc = 0;
275         ENTRY;
276
277         OBD_ALLOC(op_data, sizeof(*op_data));
278         if (op_data == NULL)
279                 return -ENOMEM;
280         
281         smfs_prepare_mdc_data(op_data, dir, NULL,
282                               (char *)dentry->d_name.name,
283                               dentry->d_name.len, mode);
284
285         mds_rec_get_id(dir, &op_data->id1);
286
287         PACK_KML_REC_INIT(buffer, MDS_REINT);
288         mkpi = (struct mds_kml_pack_info *)buffer;
289
290         mkpi->mpi_bufcount = 2;
291         mkpi->mpi_size[0] = sizeof(struct mds_rec_unlink);
292         mkpi->mpi_size[1] = op_data->namelen + 1;
293
294         msg = (struct lustre_msg *)(buffer + sizeof(*mkpi));
295         lustre_init_msg(msg, mkpi->mpi_bufcount, mkpi->mpi_size, NULL);
296
297         tmp = mdc_unlink_pack(msg, 0, op_data);
298
299         mkpi->mpi_total_size = tmp - (void *)msg;
300         rc = mkpi->mpi_total_size + sizeof(*mkpi) + sizeof(int);
301         OBD_FREE(op_data, sizeof(*op_data));
302         RETURN(rc);
303 }
304
305 static int mds_rec_rename_pack(char *buffer, struct dentry *dentry,
306                                struct inode *dir, void *data1, void *data2)
307 {
308         struct dentry *new_dentry = (struct dentry *)data2;
309         struct inode *new_dir = (struct inode *)data1;
310         struct mds_kml_pack_info *mkpi;
311         struct lustre_msg *msg = NULL;
312         struct mdc_op_data *op_data;
313         struct mds_rec_rename *rec;
314         void *tmp = NULL;
315         int rc = 0;
316         ENTRY;
317
318         OBD_ALLOC(op_data, sizeof(*op_data));
319         if (op_data == NULL)
320                 return -ENOMEM;
321         smfs_prepare_mdc_data(op_data, dir, new_dir, NULL, 0, 0);
322
323         mds_rec_get_id(dir, &op_data->id1);
324         mds_rec_get_id(new_dir, &op_data->id2);
325
326         PACK_KML_REC_INIT(buffer, MDS_REINT);
327         mkpi = (struct mds_kml_pack_info *)buffer;
328
329         mkpi->mpi_bufcount = 3;
330         mkpi->mpi_size[0] = sizeof(struct mds_rec_rename);
331         mkpi->mpi_size[1] = dentry->d_name.len + 1;
332         mkpi->mpi_size[2] = new_dentry->d_name.len + 1;
333
334         rec = (struct mds_rec_rename *)(buffer + sizeof(*mkpi));
335
336         msg = (struct lustre_msg *)(buffer + sizeof(*mkpi));
337         lustre_init_msg(msg, mkpi->mpi_bufcount, mkpi->mpi_size, NULL);
338
339         tmp = mdc_rename_pack(msg, 0, op_data, (char *)dentry->d_name.name,
340                               dentry->d_name.len, (char *)new_dentry->d_name.name,
341                               new_dentry->d_name.len);
342
343         mkpi->mpi_total_size = tmp - (void *)msg;
344         rc = mkpi->mpi_total_size + sizeof(*mkpi) + sizeof(int);
345         OBD_FREE(op_data, sizeof(*op_data));
346         RETURN(rc);
347 }
348
349 typedef int (*mds_pack_rec_func)(char *, struct dentry *,
350                                  struct inode *, void *, void *);
351
352 static mds_pack_rec_func mds_kml_pack[REINT_MAX + 1] = {
353         [REINT_LINK]    mds_rec_link_pack,
354         [REINT_SETATTR] mds_rec_setattr_pack,
355         [REINT_CREATE]  mds_rec_create_pack,
356         [REINT_UNLINK]  mds_rec_unlink_pack,
357         [REINT_RENAME]  mds_rec_rename_pack,
358         [REINT_SETXATTR] mds_rec_setxattr_pack,
359 };
360
361 int mds_rec_pack(int op, char *buffer, struct dentry *dentry, 
362                  struct inode *dir, void *arg, void *arg2)
363 {
364         return mds_kml_pack[op](buffer, dentry, dir, arg, arg2);
365 }
366
367
368