Whamcloud - gitweb
Doing endian conversion on constant instead of variable according to andreas advices...
[fs/lustre-release.git] / lustre / obdclass / llog_ioctl.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *   You should have received a copy of the GNU General Public License
5  *   along with Lustre; if not, write to the Free Software
6  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
7  */
8
9 #define DEBUG_SUBSYSTEM S_LOG
10
11 #ifndef EXPORT_SYMTAB
12 #define EXPORT_SYMTAB
13 #endif
14
15 #include <linux/fs.h>
16 #include <linux/obd_class.h>
17 #include <linux/lustre_log.h>
18 #include <portals/list.h>
19 #include "llog_internal.h"
20
21 static int str2logid(struct llog_logid *logid, char *str, int len)
22 {
23         char *start, *end, *endp;
24         
25         start = str;
26         if (*start != '#')
27                 RETURN(-EINVAL);
28         
29         start++;
30         if (start - str >= len - 1)
31                 RETURN(-EINVAL);
32         end = strchr(start, '#');
33         if (end == NULL || end == start)
34                 RETURN(-EINVAL);
35
36         *end = '\0';
37         logid->lgl_oid = simple_strtoull(start, &endp, 16); 
38         if (endp != end)
39                 RETURN(-EINVAL);
40
41         start = ++end;
42         if (start - str >= len - 1)
43                 RETURN(-EINVAL);
44         end = strchr(start, '#');
45         if (end == NULL || end == start)
46                 RETURN(-EINVAL);
47
48         *end = '\0';
49         logid->lgl_ogr = simple_strtoull(start, &endp, 16);
50         if (endp != end)
51                 RETURN(-EINVAL);
52
53         start = ++end;
54         if (start - str >= len - 1)
55                 RETURN(-EINVAL);
56         logid->lgl_ogen = simple_strtoul(start, &endp, 16);
57         if (*endp != '\0')
58                 RETURN(-EINVAL);
59
60         RETURN(0);
61 }
62
63 static int llog_check_cb(struct llog_handle *handle, struct llog_rec_hdr *rec, 
64                          void *data)
65 {
66         struct obd_ioctl_data *ioc_data = (struct obd_ioctl_data *)data;
67         static int l, remains, from, to;
68         static char *out;
69         char *endp;
70         int cur_index, rc = 0;
71         
72         cur_index = le32_to_cpu(rec->lrh_index);
73         
74         if (ioc_data && (ioc_data->ioc_inllen1)) {
75                 l = 0;
76                 remains = ioc_data->ioc_inllen4 + 
77                         size_round(ioc_data->ioc_inllen1) +
78                         size_round(ioc_data->ioc_inllen2) +
79                         size_round(ioc_data->ioc_inllen3);
80                 from = simple_strtol(ioc_data->ioc_inlbuf2, &endp, 0);
81                 if (*endp != '\0')
82                         RETURN(-EINVAL);
83                 to = simple_strtol(ioc_data->ioc_inlbuf3, &endp, 0);
84                 if (*endp != '\0')
85                         RETURN(-EINVAL);
86                 ioc_data->ioc_inllen1 = 0;
87                 out = ioc_data->ioc_bulk;
88                 if (cur_index < from)
89                         RETURN(0);
90                 if (to > 0 && cur_index > to)
91                         RETURN(-LLOG_EEMPTY);
92         }
93         if (handle->lgh_hdr->llh_flags & cpu_to_le32(LLOG_F_IS_CAT)) {
94                 struct llog_logid_rec *lir = (struct llog_logid_rec *)rec;
95                 struct llog_handle *log_handle; 
96                 
97                 if (rec->lrh_type != cpu_to_le32(LLOG_LOGID_MAGIC)) { 
98                         l = snprintf(out, remains,
99                                      "[index]: %05d  [type]: %02x  [len]: %04d failed\n", 
100                                      cur_index, le32_to_cpu(rec->lrh_type),
101                                      le32_to_cpu(rec->lrh_len));
102                 }
103                 if (handle->lgh_ctxt == NULL)
104                         RETURN(-EOPNOTSUPP);
105                 llog_cat_id2handle(handle, &log_handle, &lir->lid_id);
106                 rc = llog_process(log_handle, llog_check_cb, NULL); 
107                 llog_close(log_handle);
108         } else {
109                 switch (le32_to_cpu(rec->lrh_type)) {
110                 case OST_SZ_REC:
111                 case OST_RAID1_REC:    
112                 case MDS_UNLINK_REC:
113                 case OBD_CFG_REC:      
114                 case PTL_CFG_REC:      
115                 case LLOG_HDR_MAGIC: { 
116                          l = snprintf(out, remains,
117                                      "[index]: %05d  [type]: %02x  [len]: %04d ok\n", 
118                                      cur_index, le32_to_cpu(rec->lrh_type),
119                                      le32_to_cpu(rec->lrh_len));
120                          out += l;
121                          remains -= l;
122                          if (remains <= 0) {
123                                 CERROR("not enough space for print log records\n");
124                                 RETURN(-LLOG_EEMPTY);
125                          }
126                          RETURN(0);
127                 }
128                 default: {
129                          l = snprintf(out, remains,
130                                      "[index]: %05d  [type]: %02x  [len]: %04d failed\n", 
131                                      cur_index, le32_to_cpu(rec->lrh_type),
132                                      le32_to_cpu(rec->lrh_len));
133                          out += l;
134                          remains -= l;
135                          if (remains <= 0) {
136                                 CERROR("not enough space for print log records\n");
137                                 RETURN(-LLOG_EEMPTY);
138                          }
139                          RETURN(0);
140                 } 
141                 }
142         }
143         RETURN(rc);
144 }
145
146 static int llog_print_cb(struct llog_handle *handle, struct llog_rec_hdr *rec, 
147                          void *data)
148 {
149         struct obd_ioctl_data *ioc_data = (struct obd_ioctl_data *)data;
150         static int l, remains, from, to;
151         static char *out;
152         char *endp;
153         int cur_index;
154         
155         if (ioc_data->ioc_inllen1) {
156                 l = 0;
157                 remains = ioc_data->ioc_inllen4 + 
158                         size_round(ioc_data->ioc_inllen1) +
159                         size_round(ioc_data->ioc_inllen2) +
160                         size_round(ioc_data->ioc_inllen3);
161                 from = simple_strtol(ioc_data->ioc_inlbuf2, &endp, 0);
162                 if (*endp != '\0')
163                         RETURN(-EINVAL);
164                 to = simple_strtol(ioc_data->ioc_inlbuf3, &endp, 0);
165                 if (*endp != '\0')
166                         RETURN(-EINVAL);
167                 out = ioc_data->ioc_bulk;
168                 ioc_data->ioc_inllen1 = 0;
169         }
170
171         cur_index = le32_to_cpu(rec->lrh_index);
172         if (cur_index < from)
173                 RETURN(0);
174         if (to > 0 && cur_index > to)
175                 RETURN(-LLOG_EEMPTY);
176
177         if (handle->lgh_hdr->llh_flags & cpu_to_le32(LLOG_F_IS_CAT)) {
178                 struct llog_logid_rec *lir = (struct llog_logid_rec *)rec;
179                 if (rec->lrh_type != cpu_to_le32(LLOG_LOGID_MAGIC)) {
180                         CERROR("invalid record in catalog\n");
181                         RETURN(-EINVAL);
182                 }
183
184                 l = snprintf(out, remains,
185                              "[index]: %05d  [logid]: #%llx#%llx#%08x\n",
186                              cur_index, lir->lid_id.lgl_oid, 
187                              lir->lid_id.lgl_ogr, lir->lid_id.lgl_ogen);
188         } else {
189                 l = snprintf(out, remains,
190                              "[index]: %05d  [type]: %02x  [len]: %04d\n", 
191                              cur_index, le32_to_cpu(rec->lrh_type),
192                              le32_to_cpu(rec->lrh_len));
193         }
194         out += l;
195         remains -= l;
196         if (remains <= 0) {
197                 CERROR("not enough space for print log records\n");
198                 RETURN(-LLOG_EEMPTY);
199         }
200
201         RETURN(0);
202 }
203 static int llog_remove_log(struct llog_handle *cat, struct llog_logid *logid)
204 {
205         struct llog_handle *log;
206         int rc, index = 0;
207         
208         down_write(&cat->lgh_lock);
209         rc = llog_cat_id2handle(cat, &log, logid);
210         if (rc) {
211                 CDEBUG(D_IOCTL, "cannot find log #%0llx#%0llx#%08x\n",
212                        logid->lgl_oid, logid->lgl_ogr, logid->lgl_ogen);
213                 GOTO(out, rc = -ENOENT);
214         }
215         
216         index = log->u.phd.phd_cookie.lgc_index;
217         LASSERT(index);
218         rc = llog_destroy(log);
219         if (rc) {
220                 CDEBUG(D_IOCTL, "cannot destroy log\n");
221                 GOTO(out, rc);
222         }
223         rc = llog_cancel_rec(cat, index);
224 out:
225         llog_free_handle(log);
226         up_write(&cat->lgh_lock);
227         RETURN(rc);
228
229 }
230 static int llog_delete_cb(struct llog_handle *handle, struct llog_rec_hdr *rec, 
231                          void *data)
232 {
233         struct  llog_logid_rec *lir = (struct llog_logid_rec*)rec;
234         int     rc;
235         
236         if (rec->lrh_type != cpu_to_le32(LLOG_LOGID_MAGIC))
237               return (-EINVAL); 
238         rc = llog_remove_log(handle, &lir->lid_id);
239         
240         RETURN(rc);
241 }
242
243
244 int llog_ioctl(struct llog_ctxt *ctxt, int cmd, struct obd_ioctl_data *data)
245 {
246         struct llog_logid logid;
247         int err = 0;
248         struct llog_handle *handle = NULL;
249  
250         if (*data->ioc_inlbuf1 == '#') {
251                 err = str2logid(&logid, data->ioc_inlbuf1, data->ioc_inllen1);
252                 if (err)
253                         GOTO(out, err);
254                 err = llog_create(ctxt, &handle, &logid, NULL);
255                 if (err)
256                         GOTO(out, err);        
257         } else if (*data->ioc_inlbuf1 == '$') {
258                 char *name = data->ioc_inlbuf1 + 1;
259                 err = llog_create(ctxt, &handle, NULL, name);
260                 if (err)
261                         GOTO(out, err);
262         } else {
263                 GOTO(out, err = -EINVAL);
264         }
265
266         err = llog_init_handle(handle, 0, NULL);
267         if (err) 
268                 GOTO(out_close, err = -ENOENT);
269        
270         switch (cmd) {
271         case OBD_IOC_LLOG_INFO: {
272                 int l;
273                 int remains = data->ioc_inllen2 + 
274                         size_round(data->ioc_inllen1);
275                 char *out = data->ioc_bulk;
276
277                 l = snprintf(out, remains, 
278                              "logid:            #%llx#%llx#%08x\n"
279                              "flags:            %x (%s)\n"
280                              "records count:    %d\n"
281                              "last index:       %d\n",
282                              handle->lgh_id.lgl_oid, handle->lgh_id.lgl_ogr,
283                              handle->lgh_id.lgl_ogen,
284                              le32_to_cpu(handle->lgh_hdr->llh_flags),
285                              le32_to_cpu(handle->lgh_hdr->llh_flags) & 
286                              LLOG_F_IS_CAT ? "cat" : "plain",
287                              le32_to_cpu(handle->lgh_hdr->llh_count),
288                              handle->lgh_last_idx);
289                 out += l;
290                 remains -= l;
291                 if (remains <= 0) 
292                         CERROR("not enough space for log header info\n");
293
294                 GOTO(out_close, err);
295         }
296         case OBD_IOC_LLOG_CHECK: {
297                 LASSERT(data->ioc_inllen1);
298                 err = llog_process(handle, llog_check_cb, data);
299                 if (err == -LLOG_EEMPTY)
300                         err = 0;
301                 GOTO(out_close, err);
302         }
303
304         case OBD_IOC_LLOG_PRINT: {
305                 LASSERT(data->ioc_inllen1);
306                 err = llog_process(handle, llog_print_cb, data);
307                 if (err == -LLOG_EEMPTY)
308                         err = 0;
309
310                 GOTO(out_close, err);
311         }
312         case OBD_IOC_LLOG_CANCEL: {
313                 struct llog_cookie cookie;
314                 struct llog_logid plain;
315                 char *endp;
316                 
317                 if (!(handle->lgh_hdr->llh_flags & cpu_to_le32(LLOG_F_IS_CAT)))
318                         GOTO(out_close, err = -EINVAL);
319         
320                 err = str2logid(&plain, data->ioc_inlbuf2, data->ioc_inllen2);
321                 if (err)
322                         GOTO(out_close, err);
323                 cookie.lgc_lgl = plain;
324                 cookie.lgc_index = simple_strtoul(data->ioc_inlbuf3, 
325                                                   &endp, 0);
326                 if (*endp != '\0')
327                         GOTO(out_close, err = -EINVAL);
328
329                 err = llog_cat_cancel_records(handle, 1, &cookie);
330                 GOTO(out_close, err);
331         }
332         case OBD_IOC_LLOG_REMOVE: {
333                 struct llog_logid plain;
334                 
335                 if (!(handle->lgh_hdr->llh_flags & cpu_to_le32(LLOG_F_IS_CAT)))
336                         GOTO(out_close, err = -EINVAL);
337         
338                 if (data->ioc_inlbuf2) {
339                         /*remove indicate log from the catalog*/
340                         err = str2logid(&plain, data->ioc_inlbuf2, data->ioc_inllen2);
341                         if (err)
342                                 GOTO(out_close, err);
343                         err = llog_remove_log(handle, &plain);
344                 } else {
345                         /*remove all the log of the catalog*/
346                         llog_process(handle, llog_delete_cb, NULL);
347                 }
348                 GOTO(out_close, err);
349         }
350         }
351         
352 out_close:
353         if (handle->lgh_hdr && 
354             handle->lgh_hdr->llh_flags & cpu_to_le32(LLOG_F_IS_CAT))
355                 llog_cat_put(handle);
356         else
357                 llog_close(handle);
358 out:
359         RETURN(err);
360 }
361 EXPORT_SYMBOL(llog_ioctl);
362
363 int llog_catlog_list(struct obd_device *obd, int count, 
364                      struct obd_ioctl_data *data)
365 {
366         int size, i;
367         struct llog_logid *idarray, *id;
368         char name[32] = "CATLIST";
369         char *out;
370         int l, remains, rc = 0;
371         
372         size = sizeof(*idarray) * count;
373         
374         OBD_ALLOC(idarray, size);
375         if (!idarray)
376                 RETURN(-ENOMEM);
377         memset(idarray, 0, size);
378         
379         rc = llog_get_cat_list(obd, obd, name, count, idarray);
380         if (rc) {
381                 OBD_FREE(idarray, size);
382                 RETURN(rc);
383         }
384         
385         out = data->ioc_bulk;
386         remains = data->ioc_inllen1;
387         id = idarray;
388         for (i = 0; i < count; i++) {
389                 l = snprintf(out, remains, 
390                              "catalog log: #%llx#%llx#%08x\n",
391                              id->lgl_oid, id->lgl_ogr, id->lgl_ogen);
392                 id++;
393                 out += l;
394                 remains -= l;
395                 if (remains <= 0) {
396                         CWARN("not enough memory for catlog list\n");
397                         break;
398                 }
399         }
400         OBD_FREE(idarray, size);
401         RETURN(0);
402
403 }
404 EXPORT_SYMBOL(llog_catlog_list);