Whamcloud - gitweb
3f2cd68911b3d7937530caa3908679c72db7bce5
[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 /* Format: [0x64BIT_INT - 0x64BIT_INT] + 32 bytes just in case */
58 #define MAX_FID_RANGE_STRLEN (32 + 2 * 2 * sizeof(__u64))
59 /**
60  * Reduce the SEQ range allocated to a node to a strict subset of the range
61  * currently-allocated SEQ range.  If the specified range is "clear", then
62  * drop all allocated sequences and request a new one from the master.
63  *
64  * Note: this function should only be used for testing, it is not necessarily
65  * safe for production use.
66  */
67 static int
68 lprocfs_fid_write_common(const char __user *buffer, size_t count,
69                                 struct lu_seq_range *range)
70 {
71         struct lu_seq_range tmp = { 0, };
72         int rc;
73         char kernbuf[MAX_FID_RANGE_STRLEN];
74         ENTRY;
75
76         LASSERT(range != NULL);
77
78         if (count >= sizeof(kernbuf))
79                 RETURN(-EINVAL);
80
81         if (copy_from_user(kernbuf, buffer, count))
82                 RETURN(-EFAULT);
83
84         kernbuf[count] = 0;
85
86         if (count == 5 && strcmp(kernbuf, "clear") == 0) {
87                 memset(range, 0, sizeof(*range));
88                 RETURN(0);
89         }
90
91         /* of the form "[0x0000000240000400 - 0x000000028000400]" */
92         rc = sscanf(kernbuf, "[%llx - %llx]\n",
93                     (long long unsigned *)&tmp.lsr_start,
94                     (long long unsigned *)&tmp.lsr_end);
95         if (!range_is_sane(&tmp) || range_is_zero(&tmp) ||
96             tmp.lsr_start < range->lsr_start || tmp.lsr_end > range->lsr_end)
97                 RETURN(-EINVAL);
98         *range = tmp;
99         RETURN(0);
100 }
101
102 #ifdef HAVE_SERVER_SUPPORT
103 /*
104  * Server side procfs stuff.
105  */
106 static ssize_t
107 lprocfs_server_fid_space_seq_write(struct file *file, const char __user *buffer,
108                                         size_t count, loff_t *off)
109 {
110         struct lu_server_seq *seq = ((struct seq_file *)file->private_data)->private;
111         int rc;
112         ENTRY;
113
114         LASSERT(seq != NULL);
115
116         mutex_lock(&seq->lss_mutex);
117         rc = lprocfs_fid_write_common(buffer, count, &seq->lss_space);
118         if (rc == 0) {
119                 CDEBUG(D_INFO, "%s: Space: "DRANGE"\n",
120                         seq->lss_name, PRANGE(&seq->lss_space));
121         }
122         mutex_unlock(&seq->lss_mutex);
123
124         RETURN(count);
125 }
126
127 static int
128 lprocfs_server_fid_space_seq_show(struct seq_file *m, void *unused)
129 {
130         struct lu_server_seq *seq = (struct lu_server_seq *)m->private;
131         int rc;
132         ENTRY;
133
134         LASSERT(seq != NULL);
135
136         mutex_lock(&seq->lss_mutex);
137         rc = seq_printf(m, "["LPX64" - "LPX64"]:%x:%s\n",
138                         PRANGE(&seq->lss_space));
139         mutex_unlock(&seq->lss_mutex);
140
141         RETURN(rc);
142 }
143
144 static int
145 lprocfs_server_fid_server_seq_show(struct seq_file *m, void *unused)
146 {
147         struct lu_server_seq *seq = (struct lu_server_seq *)m->private;
148         struct client_obd *cli;
149         int rc;
150         ENTRY;
151
152         LASSERT(seq != NULL);
153
154         if (seq->lss_cli) {
155                 if (seq->lss_cli->lcs_exp != NULL) {
156                         cli = &seq->lss_cli->lcs_exp->exp_obd->u.cli;
157                         rc = seq_printf(m, "%s\n", cli->cl_target_uuid.uuid);
158                 } else {
159                         rc = seq_printf(m, "%s\n",
160                                         seq->lss_cli->lcs_srv->lss_name);
161                 }
162         } else {
163                 rc = seq_printf(m, "<none>\n");
164         }
165
166         RETURN(rc);
167 }
168
169 static ssize_t
170 lprocfs_server_fid_width_seq_write(struct file *file, const char __user *buffer,
171                                         size_t count, loff_t *off)
172 {
173         struct lu_server_seq *seq = ((struct seq_file *)file->private_data)->private;
174         int rc, val;
175         ENTRY;
176
177         LASSERT(seq != NULL);
178
179         mutex_lock(&seq->lss_mutex);
180
181         rc = lprocfs_write_helper(buffer, count, &val);
182         if (rc != 0) {
183                 CERROR("%s: invalid width.\n", seq->lss_name);
184                 GOTO(out_unlock, count = rc);
185         }
186
187         seq->lss_width = val;
188
189         CDEBUG(D_INFO, "%s: Width: "LPU64"\n",
190                seq->lss_name, seq->lss_width);
191 out_unlock:
192         mutex_unlock(&seq->lss_mutex);
193
194         RETURN(count);
195 }
196
197 static int
198 lprocfs_server_fid_width_seq_show(struct seq_file *m, void *unused)
199 {
200         struct lu_server_seq *seq = (struct lu_server_seq *)m->private;
201         int rc;
202         ENTRY;
203
204         LASSERT(seq != NULL);
205
206         mutex_lock(&seq->lss_mutex);
207         rc = seq_printf(m, LPU64"\n", seq->lss_width);
208         mutex_unlock(&seq->lss_mutex);
209
210         RETURN(rc);
211 }
212
213 LPROC_SEQ_FOPS(lprocfs_server_fid_space);
214 LPROC_SEQ_FOPS(lprocfs_server_fid_width);
215 LPROC_SEQ_FOPS_RO(lprocfs_server_fid_server);
216
217 struct lprocfs_seq_vars seq_server_proc_list[] = {
218         { .name =       "space",
219           .fops =       &lprocfs_server_fid_space_fops  },
220         { .name =       "width",
221           .fops =       &lprocfs_server_fid_width_fops  },
222         { .name =       "server",
223           .fops =       &lprocfs_server_fid_server_fops },
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         struct dt_key           *key;
247         int                     rc;
248
249         if (param == NULL || param->fsp_stop)
250                 return NULL;
251
252         fld = param->fsp_fld;
253         obj = fld->lsf_obj;
254         LASSERT(obj != NULL);
255         iops = &obj->do_index_ops->dio_it;
256
257         rc = iops->load(&param->fsp_env, param->fsp_it, *pos);
258         if (rc <= 0)
259                 return NULL;
260
261         key = iops->key(&param->fsp_env, param->fsp_it);
262         if (IS_ERR(key))
263                 return NULL;
264
265         *pos = be64_to_cpu(*(__u64 *)key);
266
267         return param;
268 }
269
270 static void fldb_seq_stop(struct seq_file *p, void *v)
271 {
272         struct fld_seq_param    *param = p->private;
273         const struct dt_it_ops  *iops;
274         struct lu_server_fld    *fld;
275         struct dt_object        *obj;
276
277         if (param == NULL)
278                 return;
279
280         fld = param->fsp_fld;
281         obj = fld->lsf_obj;
282         LASSERT(obj != NULL);
283         iops = &obj->do_index_ops->dio_it;
284
285         iops->put(&param->fsp_env, param->fsp_it);
286 }
287
288 static void *fldb_seq_next(struct seq_file *p, void *v, loff_t *pos)
289 {
290         struct fld_seq_param    *param = p->private;
291         struct lu_server_fld    *fld;
292         struct dt_object        *obj;
293         const struct dt_it_ops  *iops;
294         int                     rc;
295
296         if (param == NULL || param->fsp_stop)
297                 return NULL;
298
299         fld = param->fsp_fld;
300         obj = fld->lsf_obj;
301         LASSERT(obj != NULL);
302         iops = &obj->do_index_ops->dio_it;
303
304         rc = iops->next(&param->fsp_env, param->fsp_it);
305         if (rc > 0) {
306                 param->fsp_stop = 1;
307                 return NULL;
308         }
309
310         *pos = be64_to_cpu(*(__u64 *)iops->key(&param->fsp_env, param->fsp_it));
311         return param;
312 }
313
314 static int fldb_seq_show(struct seq_file *p, void *v)
315 {
316         struct fld_seq_param    *param = p->private;
317         struct lu_server_fld    *fld;
318         struct dt_object        *obj;
319         const struct dt_it_ops  *iops;
320         struct lu_seq_range      fld_rec;
321         int                     rc;
322
323         if (param == NULL || param->fsp_stop)
324                 return 0;
325
326         fld = param->fsp_fld;
327         obj = fld->lsf_obj;
328         LASSERT(obj != NULL);
329         iops = &obj->do_index_ops->dio_it;
330
331         rc = iops->rec(&param->fsp_env, param->fsp_it,
332                        (struct dt_rec *)&fld_rec, 0);
333         if (rc != 0) {
334                 CERROR("%s: read record error: rc = %d\n",
335                        fld->lsf_name, rc);
336         } else if (fld_rec.lsr_start != 0) {
337                 range_be_to_cpu(&fld_rec, &fld_rec);
338                 rc = seq_printf(p, DRANGE"\n", PRANGE(&fld_rec));
339         }
340
341         return rc;
342 }
343
344 struct seq_operations fldb_sops = {
345         .start = fldb_seq_start,
346         .stop = fldb_seq_stop,
347         .next = fldb_seq_next,
348         .show = fldb_seq_show,
349 };
350
351 static int fldb_seq_open(struct inode *inode, struct file *file)
352 {
353         struct seq_file         *seq;
354         struct lu_server_seq    *ss = (struct lu_server_seq *) PDE_DATA(inode);
355         struct lu_server_fld    *fld;
356         struct dt_object        *obj;
357         const struct dt_it_ops  *iops;
358         struct fld_seq_param    *param = NULL;
359         int                     env_init = 0;
360         int                     rc;
361
362         fld = ss->lss_site->ss_server_fld;
363         LASSERT(fld != NULL);
364
365         LPROCFS_ENTRY_CHECK(PDE(inode));
366         rc = seq_open(file, &fldb_sops);
367         if (rc)
368                 return rc;
369
370         obj = fld->lsf_obj;
371         if (obj == NULL) {
372                 seq = file->private_data;
373                 seq->private = NULL;
374                 return 0;
375         }
376
377         OBD_ALLOC_PTR(param);
378         if (param == NULL)
379                 GOTO(out, rc = -ENOMEM);
380
381         rc = lu_env_init(&param->fsp_env, LCT_MD_THREAD);
382         if (rc != 0)
383                 GOTO(out, rc);
384
385         env_init = 1;
386         iops = &obj->do_index_ops->dio_it;
387         param->fsp_it = iops->init(&param->fsp_env, obj, 0, NULL);
388         if (IS_ERR(param->fsp_it))
389                 GOTO(out, rc = PTR_ERR(param->fsp_it));
390
391         param->fsp_fld = fld;
392         param->fsp_seq = ss;
393         param->fsp_stop = 0;
394
395         seq = file->private_data;
396         seq->private = param;
397 out:
398         if (rc != 0) {
399                 if (env_init == 1)
400                         lu_env_fini(&param->fsp_env);
401                 if (param != NULL)
402                         OBD_FREE_PTR(param);
403         }
404         return rc;
405 }
406
407 static int fldb_seq_release(struct inode *inode, struct file *file)
408 {
409         struct seq_file         *seq = file->private_data;
410         struct fld_seq_param    *param;
411         struct lu_server_fld    *fld;
412         struct dt_object        *obj;
413         const struct dt_it_ops  *iops;
414
415         param = seq->private;
416         if (param == NULL) {
417                 lprocfs_seq_release(inode, file);
418                 return 0;
419         }
420
421         fld = param->fsp_fld;
422         obj = fld->lsf_obj;
423         LASSERT(obj != NULL);
424         iops = &obj->do_index_ops->dio_it;
425
426         LASSERT(iops != NULL);
427         LASSERT(param->fsp_it != NULL);
428         iops->fini(&param->fsp_env, param->fsp_it);
429         lu_env_fini(&param->fsp_env);
430         OBD_FREE_PTR(param);
431         lprocfs_seq_release(inode, file);
432
433         return 0;
434 }
435
436 static ssize_t fldb_seq_write(struct file *file, const char __user *buf,
437                               size_t len, loff_t *off)
438 {
439         struct seq_file         *seq = file->private_data;
440         struct fld_seq_param    *param;
441         struct lu_seq_range      range;
442         int                      rc = 0;
443         char                     _buffer[MAX_FID_RANGE_STRLEN];
444         char                    *buffer = _buffer;
445         ENTRY;
446
447         param = seq->private;
448         if (param == NULL)
449                 RETURN(-EINVAL);
450
451         if (len >= sizeof(_buffer))
452                 RETURN(-EINVAL);
453
454         if (copy_from_user(buffer, buf, len))
455                 GOTO(out, rc = -EFAULT);
456         buffer[len] = 0;
457
458         /*
459          * format - [0x0000000200000007-0x0000000200000008):0:mdt
460          */
461         if (*buffer != '[')
462                 GOTO(out, rc = -EINVAL);
463         buffer++;
464
465         range.lsr_start = simple_strtoull(buffer, &buffer, 0);
466         if (*buffer != '-')
467                 GOTO(out, rc = -EINVAL);
468         buffer++;
469
470         range.lsr_end = simple_strtoull(buffer, &buffer, 0);
471         if (*buffer != ')')
472                 GOTO(out, rc = -EINVAL);
473         buffer++;
474         if (*buffer != ':')
475                 GOTO(out, rc = -EINVAL);
476         buffer++;
477
478         range.lsr_index = simple_strtoul(buffer, &buffer, 0);
479         if (*buffer != ':')
480                 GOTO(out, rc = -EINVAL);
481         buffer++;
482
483         if (strncmp(buffer, "mdt", 3) == 0)
484                 range.lsr_flags = LU_SEQ_RANGE_MDT;
485         else if (strncmp(buffer, "ost", 3) == 0)
486                 range.lsr_flags = LU_SEQ_RANGE_OST;
487         else
488                 GOTO(out, rc = -EINVAL);
489
490         rc = seq_server_alloc_spec(param->fsp_seq->lss_site->ss_control_seq,
491                                    &range, &param->fsp_env);
492
493 out:
494         RETURN(rc < 0 ? rc : len);
495 }
496
497 const struct file_operations seq_fld_proc_seq_fops = {
498         .owner   = THIS_MODULE,
499         .open    = fldb_seq_open,
500         .read    = seq_read,
501         .write   = fldb_seq_write,
502         .release = fldb_seq_release,
503 };
504
505 #endif /* HAVE_SERVER_SUPPORT */
506
507 /* Client side procfs stuff */
508 static ssize_t
509 lprocfs_client_fid_space_seq_write(struct file *file, const char __user *buffer,
510                                    size_t count, loff_t *off)
511 {
512         struct lu_client_seq *seq = ((struct seq_file *)file->private_data)->private;
513         int rc;
514         ENTRY;
515
516         LASSERT(seq != NULL);
517
518         mutex_lock(&seq->lcs_mutex);
519         rc = lprocfs_fid_write_common(buffer, count, &seq->lcs_space);
520         if (rc == 0) {
521                 CDEBUG(D_INFO, "%s: Space: "DRANGE"\n",
522                        seq->lcs_name, PRANGE(&seq->lcs_space));
523         }
524
525         mutex_unlock(&seq->lcs_mutex);
526
527         RETURN(count);
528 }
529
530 static int
531 lprocfs_client_fid_space_seq_show(struct seq_file *m, void *unused)
532 {
533         struct lu_client_seq *seq = (struct lu_client_seq *)m->private;
534         int rc;
535         ENTRY;
536
537         LASSERT(seq != NULL);
538
539         mutex_lock(&seq->lcs_mutex);
540         rc = seq_printf(m, "["LPX64" - "LPX64"]:%x:%s\n",
541                         PRANGE(&seq->lcs_space));
542         mutex_unlock(&seq->lcs_mutex);
543
544         RETURN(rc);
545 }
546
547 static ssize_t
548 lprocfs_client_fid_width_seq_write(struct file *file, const char __user *buffer,
549                                    size_t count, loff_t *off)
550 {
551         struct lu_client_seq *seq = ((struct seq_file *)file->private_data)->private;
552         __u64  max;
553         int rc, val;
554         ENTRY;
555
556         LASSERT(seq != NULL);
557
558         mutex_lock(&seq->lcs_mutex);
559
560         rc = lprocfs_write_helper(buffer, count, &val);
561         if (rc) {
562                 mutex_unlock(&seq->lcs_mutex);
563                 RETURN(rc);
564         }
565
566         if (seq->lcs_type == LUSTRE_SEQ_DATA)
567                 max = LUSTRE_DATA_SEQ_MAX_WIDTH;
568         else
569                 max = LUSTRE_METADATA_SEQ_MAX_WIDTH;
570
571         if (val <= max && val > 0) {
572                 seq->lcs_width = val;
573
574                 if (rc == 0) {
575                         CDEBUG(D_INFO, "%s: Sequence size: "LPU64"\n",
576                                seq->lcs_name, seq->lcs_width);
577                 }
578         }
579         mutex_unlock(&seq->lcs_mutex);
580
581         RETURN(count);
582 }
583
584 static int
585 lprocfs_client_fid_width_seq_show(struct seq_file *m, void *unused)
586 {
587         struct lu_client_seq *seq = (struct lu_client_seq *)m->private;
588         int rc;
589         ENTRY;
590
591         LASSERT(seq != NULL);
592
593         mutex_lock(&seq->lcs_mutex);
594         rc = seq_printf(m, LPU64"\n", seq->lcs_width);
595         mutex_unlock(&seq->lcs_mutex);
596
597         RETURN(rc);
598 }
599
600 static int
601 lprocfs_client_fid_fid_seq_show(struct seq_file *m, void *unused)
602 {
603         struct lu_client_seq *seq = (struct lu_client_seq *)m->private;
604         int rc;
605         ENTRY;
606
607         LASSERT(seq != NULL);
608
609         mutex_lock(&seq->lcs_mutex);
610         rc = seq_printf(m, DFID"\n", PFID(&seq->lcs_fid));
611         mutex_unlock(&seq->lcs_mutex);
612
613         RETURN(rc);
614 }
615
616 static int
617 lprocfs_client_fid_server_seq_show(struct seq_file *m, void *unused)
618 {
619         struct lu_client_seq *seq = (struct lu_client_seq *)m->private;
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 = seq_printf(m, "%s\n", cli->cl_target_uuid.uuid);
629         } else {
630                 rc = seq_printf(m, "%s\n", seq->lcs_srv->lss_name);
631         }
632         RETURN(rc);
633 }
634
635 LPROC_SEQ_FOPS(lprocfs_client_fid_space);
636 LPROC_SEQ_FOPS(lprocfs_client_fid_width);
637 LPROC_SEQ_FOPS_RO(lprocfs_client_fid_server);
638 LPROC_SEQ_FOPS_RO(lprocfs_client_fid_fid);
639
640 struct lprocfs_seq_vars seq_client_proc_list[] = {
641         { .name =       "space",
642           .fops =       &lprocfs_client_fid_space_fops  },
643         { .name =       "width",
644           .fops =       &lprocfs_client_fid_width_fops  },
645         { .name =       "server",
646           .fops =       &lprocfs_client_fid_server_fops },
647         { .name =       "fid",
648           .fops =       &lprocfs_client_fid_fid_fops    },
649         { NULL }
650 };
651 #endif