Whamcloud - gitweb
7d70870ea45eb779e15fd4cb40ace480452d4c66
[fs/lustre-release.git] / lustre / fid / lproc_fid.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2011, 2013, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/fid/lproc_fid.c
37  *
38  * Lustre Sequence Manager
39  *
40  * Author: Yury Umanets <umka@clusterfs.com>
41  */
42
43 #define DEBUG_SUBSYSTEM S_FID
44
45 #include <libcfs/libcfs.h>
46 #include <linux/module.h>
47 #include <obd.h>
48 #include <obd_class.h>
49 #include <obd_support.h>
50 #include <lustre_fid.h>
51 #include <lprocfs_status.h>
52 #include "fid_internal.h"
53 #include <md_object.h>
54
55 #ifdef LPROCFS
56 /*
57  * Note: this function is only used for testing, it is no safe for production
58  * use.
59  */
60 static int
61 seq_proc_write_common(struct file *file, const char *buffer,
62                       unsigned long count, void *data,
63                       struct lu_seq_range *range)
64 {
65         struct lu_seq_range tmp;
66         int rc;
67         ENTRY;
68
69         LASSERT(range != NULL);
70
71         if (count == 5 && strcmp(buffer, "clear") == 0) {
72                 memset(range, 0, sizeof(*range));
73                 RETURN(0);
74         }
75
76         rc = sscanf(buffer, "[%llx - %llx]\n",
77                     (long long unsigned *)&tmp.lsr_start,
78                     (long long unsigned *)&tmp.lsr_end);
79         if (rc != 2 || !range_is_sane(&tmp) || range_is_zero(&tmp))
80                 RETURN(-EINVAL);
81         *range = tmp;
82         RETURN(0);
83 }
84
85 static int
86 seq_proc_read_common(char *page, char **start, off_t off,
87                      int count, int *eof, void *data,
88                      struct lu_seq_range *range)
89 {
90         int rc;
91         ENTRY;
92
93         *eof = 1;
94         rc = snprintf(page, count, "["LPX64" - "LPX64"]:%x:%s\n",
95                         PRANGE(range));
96         RETURN(rc);
97 }
98
99 #ifdef HAVE_SERVER_SUPPORT
100 /*
101  * Server side procfs stuff.
102  */
103 static int
104 seq_server_proc_write_space(struct file *file, const char *buffer,
105                             unsigned long count, void *data)
106 {
107         struct lu_server_seq *seq = (struct lu_server_seq *)data;
108         int rc;
109         ENTRY;
110
111         LASSERT(seq != NULL);
112
113         mutex_lock(&seq->lss_mutex);
114         rc = seq_proc_write_common(file, buffer, count,
115                                    data, &seq->lss_space);
116         if (rc == 0) {
117                 CDEBUG(D_INFO, "%s: Space: "DRANGE"\n",
118                        seq->lss_name, PRANGE(&seq->lss_space));
119         }
120
121         mutex_unlock(&seq->lss_mutex);
122
123         RETURN(count);
124 }
125
126 static int
127 seq_server_proc_read_space(char *page, char **start, off_t off,
128                            int count, int *eof, void *data)
129 {
130         struct lu_server_seq *seq = (struct lu_server_seq *)data;
131         int rc;
132         ENTRY;
133
134         LASSERT(seq != NULL);
135
136         mutex_lock(&seq->lss_mutex);
137         rc = seq_proc_read_common(page, start, off, count, eof,
138                                   data, &seq->lss_space);
139         mutex_unlock(&seq->lss_mutex);
140
141         RETURN(rc);
142 }
143
144 static int
145 seq_server_proc_read_server(char *page, char **start, off_t off,
146                             int count, int *eof, void *data)
147 {
148         struct lu_server_seq *seq = (struct lu_server_seq *)data;
149         struct client_obd *cli;
150         int rc;
151         ENTRY;
152
153         LASSERT(seq != NULL);
154
155         *eof = 1;
156         if (seq->lss_cli) {
157                 if (seq->lss_cli->lcs_exp != NULL) {
158                         cli = &seq->lss_cli->lcs_exp->exp_obd->u.cli;
159                         rc = snprintf(page, count, "%s\n",
160                                       cli->cl_target_uuid.uuid);
161                 } else {
162                         rc = snprintf(page, count, "%s\n",
163                                       seq->lss_cli->lcs_srv->lss_name);
164                 }
165         } else {
166                 rc = snprintf(page, count, "<none>\n");
167         }
168
169         RETURN(rc);
170 }
171
172 static int
173 seq_server_proc_write_width(struct file *file, const char *buffer,
174                             unsigned long count, void *data)
175 {
176         struct lu_server_seq *seq = (struct lu_server_seq *)data;
177         int rc, val;
178         ENTRY;
179
180         LASSERT(seq != NULL);
181
182         mutex_lock(&seq->lss_mutex);
183
184         rc = lprocfs_write_helper(buffer, count, &val);
185         if (rc != 0) {
186                 CERROR("%s: invalid width.\n", seq->lss_name);
187                 GOTO(out_unlock, rc);
188         }
189
190         seq->lss_width = val;
191
192         CDEBUG(D_INFO, "%s: Width: "LPU64"\n",
193                seq->lss_name, seq->lss_width);
194 out_unlock:
195         mutex_unlock(&seq->lss_mutex);
196
197         RETURN(count);
198 }
199
200 static int
201 seq_server_proc_read_width(char *page, char **start, off_t off,
202                            int count, int *eof, void *data)
203 {
204         struct lu_server_seq *seq = (struct lu_server_seq *)data;
205         int rc;
206         ENTRY;
207
208         LASSERT(seq != NULL);
209
210         mutex_lock(&seq->lss_mutex);
211         rc = snprintf(page, count, LPU64"\n", seq->lss_width);
212         mutex_unlock(&seq->lss_mutex);
213
214         RETURN(rc);
215 }
216
217 struct lprocfs_vars seq_server_proc_list[] = {
218         { "space",
219           seq_server_proc_read_space, seq_server_proc_write_space, NULL },
220         { "width",
221           seq_server_proc_read_width, seq_server_proc_write_width, NULL },
222         { "server",
223           seq_server_proc_read_server, NULL, NULL },
224         { NULL }
225 };
226
227 struct fld_seq_param {
228         struct lu_env           fsp_env;
229         struct dt_it            *fsp_it;
230         struct lu_server_fld    *fsp_fld;
231         struct lu_server_seq    *fsp_seq;
232         unsigned int            fsp_stop:1;
233 };
234
235 /*
236  * XXX: below is a copy of the functions in lustre/fld/lproc_fld.c.
237  * we want to avoid this duplication either by exporting the
238  * functions or merging fid and fld into a single module.
239  */
240 static void *fldb_seq_start(struct seq_file *p, loff_t *pos)
241 {
242         struct fld_seq_param    *param = p->private;
243         struct lu_server_fld    *fld;
244         struct dt_object        *obj;
245         const struct dt_it_ops  *iops;
246
247         if (param == NULL || param->fsp_stop)
248                 return NULL;
249
250         fld = param->fsp_fld;
251         obj = fld->lsf_obj;
252         LASSERT(obj != NULL);
253         iops = &obj->do_index_ops->dio_it;
254
255         iops->load(&param->fsp_env, param->fsp_it, *pos);
256
257         *pos = be64_to_cpu(*(__u64 *)iops->key(&param->fsp_env, param->fsp_it));
258         return param;
259 }
260
261 static void fldb_seq_stop(struct seq_file *p, void *v)
262 {
263         struct fld_seq_param    *param = p->private;
264         const struct dt_it_ops  *iops;
265         struct lu_server_fld    *fld;
266         struct dt_object        *obj;
267
268         if (param == NULL)
269                 return;
270
271         fld = param->fsp_fld;
272         obj = fld->lsf_obj;
273         LASSERT(obj != NULL);
274         iops = &obj->do_index_ops->dio_it;
275
276         iops->put(&param->fsp_env, param->fsp_it);
277 }
278
279 static void *fldb_seq_next(struct seq_file *p, void *v, loff_t *pos)
280 {
281         struct fld_seq_param    *param = p->private;
282         struct lu_server_fld    *fld;
283         struct dt_object        *obj;
284         const struct dt_it_ops  *iops;
285         int                     rc;
286
287         if (param == NULL || param->fsp_stop)
288                 return NULL;
289
290         fld = param->fsp_fld;
291         obj = fld->lsf_obj;
292         LASSERT(obj != NULL);
293         iops = &obj->do_index_ops->dio_it;
294
295         rc = iops->next(&param->fsp_env, param->fsp_it);
296         if (rc > 0) {
297                 param->fsp_stop = 1;
298                 return NULL;
299         }
300
301         *pos = be64_to_cpu(*(__u64 *)iops->key(&param->fsp_env, param->fsp_it));
302         return param;
303 }
304
305 static int fldb_seq_show(struct seq_file *p, void *v)
306 {
307         struct fld_seq_param    *param = p->private;
308         struct lu_server_fld    *fld;
309         struct dt_object        *obj;
310         const struct dt_it_ops  *iops;
311         struct lu_seq_range      fld_rec;
312         int                     rc;
313
314         if (param == NULL || param->fsp_stop)
315                 return 0;
316
317         fld = param->fsp_fld;
318         obj = fld->lsf_obj;
319         LASSERT(obj != NULL);
320         iops = &obj->do_index_ops->dio_it;
321
322         rc = iops->rec(&param->fsp_env, param->fsp_it,
323                        (struct dt_rec *)&fld_rec, 0);
324         if (rc != 0) {
325                 CERROR("%s: read record error: rc = %d\n",
326                        fld->lsf_name, rc);
327         } else if (fld_rec.lsr_start != 0) {
328                 range_be_to_cpu(&fld_rec, &fld_rec);
329                 rc = seq_printf(p, DRANGE"\n", PRANGE(&fld_rec));
330         }
331
332         return rc;
333 }
334
335 struct seq_operations fldb_sops = {
336         .start = fldb_seq_start,
337         .stop = fldb_seq_stop,
338         .next = fldb_seq_next,
339         .show = fldb_seq_show,
340 };
341
342 static int fldb_seq_open(struct inode *inode, struct file *file)
343 {
344         struct proc_dir_entry   *dp = PDE(inode);
345         struct seq_file         *seq;
346         struct lu_server_seq    *ss = (struct lu_server_seq *)dp->data;
347         struct lu_server_fld    *fld;
348         struct dt_object        *obj;
349         const struct dt_it_ops  *iops;
350         struct fld_seq_param    *param = NULL;
351         int                     env_init = 0;
352         int                     rc;
353
354         fld = ss->lss_site->ss_server_fld;
355         LASSERT(fld != NULL);
356
357         LPROCFS_ENTRY_CHECK(dp);
358         rc = seq_open(file, &fldb_sops);
359         if (rc)
360                 GOTO(out, rc);
361
362         obj = fld->lsf_obj;
363         if (obj == NULL) {
364                 seq = file->private_data;
365                 seq->private = NULL;
366                 return 0;
367         }
368
369         OBD_ALLOC_PTR(param);
370         if (param == NULL)
371                 GOTO(out, rc = -ENOMEM);
372
373         rc = lu_env_init(&param->fsp_env, LCT_MD_THREAD);
374         if (rc != 0)
375                 GOTO(out, rc);
376
377         env_init = 1;
378         iops = &obj->do_index_ops->dio_it;
379         param->fsp_it = iops->init(&param->fsp_env, obj, 0, NULL);
380         if (IS_ERR(param->fsp_it))
381                 GOTO(out, rc = PTR_ERR(param->fsp_it));
382
383         param->fsp_fld = fld;
384         param->fsp_seq = ss;
385         param->fsp_stop = 0;
386
387         seq = file->private_data;
388         seq->private = param;
389 out:
390         if (rc != 0) {
391                 if (env_init == 1)
392                         lu_env_fini(&param->fsp_env);
393                 if (param != NULL)
394                         OBD_FREE_PTR(param);
395         }
396         return rc;
397 }
398
399 static int fldb_seq_release(struct inode *inode, struct file *file)
400 {
401         struct seq_file         *seq = file->private_data;
402         struct fld_seq_param    *param;
403         struct lu_server_fld    *fld;
404         struct dt_object        *obj;
405         const struct dt_it_ops  *iops;
406
407         param = seq->private;
408         if (param == NULL) {
409                 lprocfs_seq_release(inode, file);
410                 return 0;
411         }
412
413         fld = param->fsp_fld;
414         obj = fld->lsf_obj;
415         LASSERT(obj != NULL);
416         iops = &obj->do_index_ops->dio_it;
417
418         LASSERT(iops != NULL);
419         LASSERT(obj != NULL);
420         LASSERT(param->fsp_it != NULL);
421         iops->fini(&param->fsp_env, param->fsp_it);
422         lu_env_fini(&param->fsp_env);
423         OBD_FREE_PTR(param);
424         lprocfs_seq_release(inode, file);
425
426         return 0;
427 }
428
429 static ssize_t fldb_seq_write(struct file *file, const char *buf,
430                               size_t len, loff_t *off)
431 {
432         struct seq_file         *seq = file->private_data;
433         struct fld_seq_param    *param;
434         struct lu_seq_range      range;
435         int                      rc = 0;
436         char                    *buffer, *_buffer;
437         ENTRY;
438
439         param = seq->private;
440         if (param == NULL)
441                 RETURN(-EINVAL);
442
443         OBD_ALLOC(buffer, len + 1);
444         if (buffer == NULL)
445                 RETURN(-ENOMEM);
446         memcpy(buffer, buf, len);
447         buffer[len] = 0;
448         _buffer = buffer;
449
450         /*
451          * format - [0x0000000200000007-0x0000000200000008):0:mdt
452          */
453         if (*buffer != '[')
454                 GOTO(out, rc = -EINVAL);
455         buffer++;
456
457         range.lsr_start = simple_strtoull(buffer, &buffer, 0);
458         if (*buffer != '-')
459                 GOTO(out, rc = -EINVAL);
460         buffer++;
461
462         range.lsr_end = simple_strtoull(buffer, &buffer, 0);
463         if (*buffer != ')')
464                 GOTO(out, rc = -EINVAL);
465         buffer++;
466         if (*buffer != ':')
467                 GOTO(out, rc = -EINVAL);
468         buffer++;
469
470         range.lsr_index = simple_strtoul(buffer, &buffer, 0);
471         if (*buffer != ':')
472                 GOTO(out, rc = -EINVAL);
473         buffer++;
474
475         if (strncmp(buffer, "mdt", 3) == 0)
476                 range.lsr_flags = LU_SEQ_RANGE_MDT;
477         else if (strncmp(buffer, "ost", 3) == 0)
478                 range.lsr_flags = LU_SEQ_RANGE_OST;
479         else
480                 GOTO(out, rc = -EINVAL);
481
482         rc = seq_server_alloc_spec(param->fsp_seq->lss_site->ss_control_seq,
483                                    &range, &param->fsp_env);
484
485 out:
486         OBD_FREE(_buffer, len + 1);
487         RETURN(rc < 0 ? rc : len);
488 }
489
490 const struct file_operations seq_fld_proc_seq_fops = {
491         .owner   = THIS_MODULE,
492         .open    = fldb_seq_open,
493         .read    = seq_read,
494         .write   = fldb_seq_write,
495         .release = fldb_seq_release,
496 };
497
498 #endif /* HAVE_SERVER_SUPPORT */
499
500 /* Client side procfs stuff */
501 static int
502 seq_client_proc_write_space(struct file *file, const char *buffer,
503                             unsigned long count, void *data)
504 {
505         struct lu_client_seq *seq = (struct lu_client_seq *)data;
506         int rc;
507         ENTRY;
508
509         LASSERT(seq != NULL);
510
511         mutex_lock(&seq->lcs_mutex);
512         rc = seq_proc_write_common(file, buffer, count,
513                                    data, &seq->lcs_space);
514
515         if (rc == 0) {
516                 CDEBUG(D_INFO, "%s: Space: "DRANGE"\n",
517                        seq->lcs_name, PRANGE(&seq->lcs_space));
518         }
519
520         mutex_unlock(&seq->lcs_mutex);
521
522         RETURN(count);
523 }
524
525 static int
526 seq_client_proc_read_space(char *page, char **start, off_t off,
527                            int count, int *eof, void *data)
528 {
529         struct lu_client_seq *seq = (struct lu_client_seq *)data;
530         int rc;
531         ENTRY;
532
533         LASSERT(seq != NULL);
534
535         mutex_lock(&seq->lcs_mutex);
536         rc = seq_proc_read_common(page, start, off, count, eof,
537                                   data, &seq->lcs_space);
538         mutex_unlock(&seq->lcs_mutex);
539
540         RETURN(rc);
541 }
542
543 static int
544 seq_client_proc_write_width(struct file *file, const char *buffer,
545                             unsigned long count, void *data)
546 {
547         struct lu_client_seq *seq = (struct lu_client_seq *)data;
548         __u64  max;
549         int rc, val;
550         ENTRY;
551
552         LASSERT(seq != NULL);
553
554         mutex_lock(&seq->lcs_mutex);
555
556         rc = lprocfs_write_helper(buffer, count, &val);
557         if (rc) {
558                 mutex_unlock(&seq->lcs_mutex);
559                 RETURN(rc);
560         }
561
562         if (seq->lcs_type == LUSTRE_SEQ_DATA)
563                 max = LUSTRE_DATA_SEQ_MAX_WIDTH;
564         else
565                 max = LUSTRE_METADATA_SEQ_MAX_WIDTH;
566
567         if (val <= max && val > 0) {
568                 seq->lcs_width = val;
569
570                 if (rc == 0) {
571                         CDEBUG(D_INFO, "%s: Sequence size: "LPU64"\n",
572                                seq->lcs_name, seq->lcs_width);
573                 }
574         }
575
576         mutex_unlock(&seq->lcs_mutex);
577
578         RETURN(count);
579 }
580
581 static int
582 seq_client_proc_read_width(char *page, char **start, off_t off,
583                            int count, int *eof, void *data)
584 {
585         struct lu_client_seq *seq = (struct lu_client_seq *)data;
586         int rc;
587         ENTRY;
588
589         LASSERT(seq != NULL);
590
591         mutex_lock(&seq->lcs_mutex);
592         rc = snprintf(page, count, LPU64"\n", seq->lcs_width);
593         mutex_unlock(&seq->lcs_mutex);
594
595         RETURN(rc);
596 }
597
598 static int
599 seq_client_proc_read_fid(char *page, char **start, off_t off,
600                          int count, int *eof, void *data)
601 {
602         struct lu_client_seq *seq = (struct lu_client_seq *)data;
603         int rc;
604         ENTRY;
605
606         LASSERT(seq != NULL);
607
608         mutex_lock(&seq->lcs_mutex);
609         rc = snprintf(page, count, DFID"\n", PFID(&seq->lcs_fid));
610         mutex_unlock(&seq->lcs_mutex);
611
612         RETURN(rc);
613 }
614
615 static int
616 seq_client_proc_read_server(char *page, char **start, off_t off,
617                             int count, int *eof, void *data)
618 {
619         struct lu_client_seq *seq = (struct lu_client_seq *)data;
620         struct client_obd *cli;
621         int rc;
622         ENTRY;
623
624         LASSERT(seq != NULL);
625
626         if (seq->lcs_exp != NULL) {
627                 cli = &seq->lcs_exp->exp_obd->u.cli;
628                 rc = snprintf(page, count, "%s\n", cli->cl_target_uuid.uuid);
629         } else {
630                 rc = snprintf(page, count, "%s\n", seq->lcs_srv->lss_name);
631         }
632         RETURN(rc);
633 }
634
635 struct lprocfs_vars seq_client_proc_list[] = {
636         { "space",    seq_client_proc_read_space, seq_client_proc_write_space, NULL },
637         { "width",    seq_client_proc_read_width, seq_client_proc_write_width, NULL },
638         { "server",   seq_client_proc_read_server, NULL, NULL },
639         { "fid",      seq_client_proc_read_fid, NULL, NULL },
640         { NULL }};
641 #endif