Whamcloud - gitweb
15a5c7435190d4d8ac6942c64eae299b149f7c82
[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.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2011, 2015, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  * Lustre is a trademark of Sun Microsystems, Inc.
31  *
32  * lustre/fid/lproc_fid.c
33  *
34  * Lustre Sequence Manager
35  *
36  * Author: Yury Umanets <umka@clusterfs.com>
37  */
38
39 #define DEBUG_SUBSYSTEM S_FID
40
41 #include <libcfs/libcfs.h>
42 #include <linux/module.h>
43 #include <obd.h>
44 #include <obd_class.h>
45 #include <obd_support.h>
46 #include <lustre_fid.h>
47 #include <lprocfs_status.h>
48 #include "fid_internal.h"
49
50 #ifdef CONFIG_PROC_FS
51
52 /* Format: [0x64BIT_INT - 0x64BIT_INT] + 32 bytes just in case */
53 #define MAX_FID_RANGE_STRLEN (32 + 2 * 2 * sizeof(__u64))
54 /**
55  * Reduce the SEQ range allocated to a node to a strict subset of the range
56  * currently-allocated SEQ range.  If the specified range is "clear", then
57  * drop all allocated sequences and request a new one from the master.
58  *
59  * Note: this function should only be used for testing, it is not necessarily
60  * safe for production use.
61  */
62 static int
63 lprocfs_fid_write_common(const char __user *buffer, size_t count,
64                                 struct lu_seq_range *range)
65 {
66         struct lu_seq_range tmp = {
67                 .lsr_start = 0,
68         };
69         char kernbuf[MAX_FID_RANGE_STRLEN];
70         ENTRY;
71
72         LASSERT(range != NULL);
73
74         if (count >= sizeof(kernbuf))
75                 RETURN(-EINVAL);
76
77         if (copy_from_user(kernbuf, buffer, count))
78                 RETURN(-EFAULT);
79
80         kernbuf[count] = 0;
81
82         if (count == 5 && strcmp(kernbuf, "clear") == 0) {
83                 memset(range, 0, sizeof(*range));
84                 RETURN(0);
85         }
86
87         /* of the form "[0x0000000240000400 - 0x000000028000400]" */
88         sscanf(kernbuf, "[%llx - %llx]\n",
89                (long long unsigned *)&tmp.lsr_start,
90                (long long unsigned *)&tmp.lsr_end);
91         if (!lu_seq_range_is_sane(&tmp) || lu_seq_range_is_zero(&tmp) ||
92             tmp.lsr_start < range->lsr_start || tmp.lsr_end > range->lsr_end)
93                 RETURN(-EINVAL);
94         *range = tmp;
95         RETURN(0);
96 }
97
98 #ifdef HAVE_SERVER_SUPPORT
99 /*
100  * Server side procfs stuff.
101  */
102 static ssize_t
103 lprocfs_server_fid_space_seq_write(struct file *file, const char __user *buffer,
104                                         size_t count, loff_t *off)
105 {
106         struct lu_server_seq *seq = ((struct seq_file *)file->private_data)->private;
107         int rc;
108         ENTRY;
109
110         LASSERT(seq != NULL);
111
112         mutex_lock(&seq->lss_mutex);
113         rc = lprocfs_fid_write_common(buffer, count, &seq->lss_space);
114         if (rc == 0) {
115                 CDEBUG(D_INFO, "%s: Space: "DRANGE"\n",
116                         seq->lss_name, PRANGE(&seq->lss_space));
117         }
118         mutex_unlock(&seq->lss_mutex);
119
120         RETURN(count);
121 }
122
123 static int
124 lprocfs_server_fid_space_seq_show(struct seq_file *m, void *unused)
125 {
126         struct lu_server_seq *seq = (struct lu_server_seq *)m->private;
127         ENTRY;
128
129         LASSERT(seq != NULL);
130
131         mutex_lock(&seq->lss_mutex);
132         seq_printf(m, "[%#llx - %#llx]:%x:%s\n", PRANGE(&seq->lss_space));
133         mutex_unlock(&seq->lss_mutex);
134
135         RETURN(0);
136 }
137
138 static int
139 lprocfs_server_fid_server_seq_show(struct seq_file *m, void *unused)
140 {
141         struct lu_server_seq *seq = (struct lu_server_seq *)m->private;
142         struct client_obd *cli;
143         ENTRY;
144
145         LASSERT(seq != NULL);
146
147         if (seq->lss_cli) {
148                 if (seq->lss_cli->lcs_exp != NULL) {
149                         cli = &seq->lss_cli->lcs_exp->exp_obd->u.cli;
150                         seq_printf(m, "%s\n", cli->cl_target_uuid.uuid);
151                 } else {
152                         seq_printf(m, "%s\n", seq->lss_cli->lcs_srv->lss_name);
153                 }
154         } else {
155                 seq_puts(m, "<none>\n");
156         }
157
158         RETURN(0);
159 }
160
161 static ssize_t
162 lprocfs_server_fid_width_seq_write(struct file *file, const char __user *buffer,
163                                         size_t count, loff_t *off)
164 {
165         struct seq_file *m = file->private_data;
166         struct lu_server_seq *seq = m->private;
167         int rc;
168         ENTRY;
169
170         LASSERT(seq != NULL);
171
172         mutex_lock(&seq->lss_mutex);
173
174         rc = kstrtoull_from_user(buffer, count, 0, &seq->lss_width);
175         if (rc) {
176                 CERROR("%s: invalid FID sequence width: rc = %d\n",
177                        seq->lss_name, rc);
178                 GOTO(out_unlock, count = rc);
179         }
180
181         CDEBUG(D_INFO, "%s: Width: %llu\n",
182                seq->lss_name, seq->lss_width);
183 out_unlock:
184         mutex_unlock(&seq->lss_mutex);
185
186         RETURN(count);
187 }
188
189 static int
190 lprocfs_server_fid_width_seq_show(struct seq_file *m, void *unused)
191 {
192         struct lu_server_seq *seq = (struct lu_server_seq *)m->private;
193         ENTRY;
194
195         LASSERT(seq != NULL);
196
197         mutex_lock(&seq->lss_mutex);
198         seq_printf(m, "%llu\n", seq->lss_width);
199         mutex_unlock(&seq->lss_mutex);
200
201         RETURN(0);
202 }
203
204 LPROC_SEQ_FOPS(lprocfs_server_fid_space);
205 LPROC_SEQ_FOPS(lprocfs_server_fid_width);
206 LPROC_SEQ_FOPS_RO(lprocfs_server_fid_server);
207
208 struct lprocfs_vars seq_server_proc_list[] = {
209         { .name =       "space",
210           .fops =       &lprocfs_server_fid_space_fops  },
211         { .name =       "width",
212           .fops =       &lprocfs_server_fid_width_fops  },
213         { .name =       "server",
214           .fops =       &lprocfs_server_fid_server_fops },
215         { NULL }
216 };
217
218 struct fld_seq_param {
219         struct lu_env           fsp_env;
220         struct dt_it            *fsp_it;
221         struct lu_server_fld    *fsp_fld;
222         struct lu_server_seq    *fsp_seq;
223         unsigned int            fsp_stop:1;
224 };
225
226 /*
227  * XXX: below is a copy of the functions in lustre/fld/lproc_fld.c.
228  * we want to avoid this duplication either by exporting the
229  * functions or merging fid and fld into a single module.
230  */
231 static void *fldb_seq_start(struct seq_file *p, loff_t *pos)
232 {
233         struct fld_seq_param    *param = p->private;
234         struct lu_server_fld    *fld;
235         struct dt_object        *obj;
236         const struct dt_it_ops  *iops;
237         struct dt_key           *key;
238         int                     rc;
239
240         if (param == NULL || param->fsp_stop)
241                 return NULL;
242
243         fld = param->fsp_fld;
244         obj = fld->lsf_obj;
245         LASSERT(obj != NULL);
246         iops = &obj->do_index_ops->dio_it;
247
248         rc = iops->load(&param->fsp_env, param->fsp_it, *pos);
249         if (rc <= 0)
250                 return NULL;
251
252         key = iops->key(&param->fsp_env, param->fsp_it);
253         if (IS_ERR(key))
254                 return NULL;
255
256         *pos = be64_to_cpu(*(__u64 *)key);
257
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                 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 seq_file         *seq;
345         struct lu_server_seq    *ss = (struct lu_server_seq *) PDE_DATA(inode);
346         struct lu_server_fld    *fld;
347         struct dt_object        *obj;
348         const struct dt_it_ops  *iops;
349         struct fld_seq_param    *param = NULL;
350         int                     env_init = 0;
351         int                     rc;
352
353         fld = ss->lss_site->ss_server_fld;
354         LASSERT(fld != NULL);
355
356         rc = LPROCFS_ENTRY_CHECK(inode);
357         if (rc < 0)
358                 return rc;
359
360         rc = seq_open(file, &fldb_sops);
361         if (rc)
362                 return rc;
363
364         obj = fld->lsf_obj;
365         if (obj == NULL) {
366                 seq = file->private_data;
367                 seq->private = NULL;
368                 return 0;
369         }
370
371         OBD_ALLOC_PTR(param);
372         if (param == NULL)
373                 GOTO(out, rc = -ENOMEM);
374
375         rc = lu_env_init(&param->fsp_env, LCT_MD_THREAD);
376         if (rc != 0)
377                 GOTO(out, rc);
378
379         env_init = 1;
380         iops = &obj->do_index_ops->dio_it;
381         param->fsp_it = iops->init(&param->fsp_env, obj, 0);
382         if (IS_ERR(param->fsp_it))
383                 GOTO(out, rc = PTR_ERR(param->fsp_it));
384
385         param->fsp_fld = fld;
386         param->fsp_seq = ss;
387         param->fsp_stop = 0;
388
389         seq = file->private_data;
390         seq->private = param;
391 out:
392         if (rc != 0) {
393                 if (env_init == 1)
394                         lu_env_fini(&param->fsp_env);
395                 if (param != NULL)
396                         OBD_FREE_PTR(param);
397         }
398         return rc;
399 }
400
401 static int fldb_seq_release(struct inode *inode, struct file *file)
402 {
403         struct seq_file         *seq = file->private_data;
404         struct fld_seq_param    *param;
405         struct lu_server_fld    *fld;
406         struct dt_object        *obj;
407         const struct dt_it_ops  *iops;
408
409         param = seq->private;
410         if (param == NULL) {
411                 lprocfs_seq_release(inode, file);
412                 return 0;
413         }
414
415         fld = param->fsp_fld;
416         obj = fld->lsf_obj;
417         LASSERT(obj != NULL);
418         iops = &obj->do_index_ops->dio_it;
419
420         LASSERT(iops != NULL);
421         LASSERT(param->fsp_it != NULL);
422         iops->fini(&param->fsp_env, param->fsp_it);
423         lu_env_fini(&param->fsp_env);
424         OBD_FREE_PTR(param);
425         lprocfs_seq_release(inode, file);
426
427         return 0;
428 }
429
430 static ssize_t fldb_seq_write(struct file *file, const char __user *buf,
431                               size_t len, loff_t *off)
432 {
433         struct seq_file         *seq = file->private_data;
434         struct fld_seq_param    *param;
435         struct lu_seq_range      range;
436         int                      rc = 0;
437         char                     _buffer[MAX_FID_RANGE_STRLEN];
438         char                    *buffer = _buffer;
439         ENTRY;
440
441         param = seq->private;
442         if (param == NULL)
443                 RETURN(-EINVAL);
444
445         if (len >= sizeof(_buffer))
446                 RETURN(-EINVAL);
447
448         if (copy_from_user(buffer, buf, len))
449                 GOTO(out, rc = -EFAULT);
450         buffer[len] = 0;
451
452         /*
453          * format - [0x0000000200000007-0x0000000200000008):0:mdt
454          */
455         if (*buffer != '[')
456                 GOTO(out, rc = -EINVAL);
457         buffer++;
458
459         range.lsr_start = simple_strtoull(buffer, &buffer, 0);
460         if (*buffer != '-')
461                 GOTO(out, rc = -EINVAL);
462         buffer++;
463
464         range.lsr_end = simple_strtoull(buffer, &buffer, 0);
465         if (*buffer != ')')
466                 GOTO(out, rc = -EINVAL);
467         buffer++;
468         if (*buffer != ':')
469                 GOTO(out, rc = -EINVAL);
470         buffer++;
471
472         range.lsr_index = simple_strtoul(buffer, &buffer, 0);
473         if (*buffer != ':')
474                 GOTO(out, rc = -EINVAL);
475         buffer++;
476
477         if (strncmp(buffer, "mdt", 3) == 0)
478                 range.lsr_flags = LU_SEQ_RANGE_MDT;
479         else if (strncmp(buffer, "ost", 3) == 0)
480                 range.lsr_flags = LU_SEQ_RANGE_OST;
481         else
482                 GOTO(out, rc = -EINVAL);
483
484         rc = seq_server_alloc_spec(param->fsp_seq->lss_site->ss_control_seq,
485                                    &range, &param->fsp_env);
486
487 out:
488         RETURN(rc < 0 ? rc : len);
489 }
490
491 const struct file_operations seq_fld_proc_seq_fops = {
492         .owner   = THIS_MODULE,
493         .open    = fldb_seq_open,
494         .read    = seq_read,
495         .write   = fldb_seq_write,
496         .release = fldb_seq_release,
497 };
498
499 #endif /* HAVE_SERVER_SUPPORT */
500
501 /* Client side procfs stuff */
502 static ssize_t
503 lprocfs_client_fid_space_seq_write(struct file *file, const char __user *buffer,
504                                    size_t count, loff_t *off)
505 {
506         struct lu_client_seq *seq = ((struct seq_file *)file->private_data)->private;
507         int rc;
508         ENTRY;
509
510         LASSERT(seq != NULL);
511
512         mutex_lock(&seq->lcs_mutex);
513         rc = lprocfs_fid_write_common(buffer, count, &seq->lcs_space);
514         if (rc == 0) {
515                 CDEBUG(D_INFO, "%s: Space: "DRANGE"\n",
516                        seq->lcs_name, PRANGE(&seq->lcs_space));
517         }
518
519         mutex_unlock(&seq->lcs_mutex);
520
521         RETURN(count);
522 }
523
524 static int
525 lprocfs_client_fid_space_seq_show(struct seq_file *m, void *unused)
526 {
527         struct lu_client_seq *seq = (struct lu_client_seq *)m->private;
528         ENTRY;
529
530         LASSERT(seq != NULL);
531
532         mutex_lock(&seq->lcs_mutex);
533         seq_printf(m, "[%#llx - %#llx]:%x:%s\n",
534                    PRANGE(&seq->lcs_space));
535         mutex_unlock(&seq->lcs_mutex);
536
537         RETURN(0);
538 }
539
540 static ssize_t
541 lprocfs_client_fid_width_seq_write(struct file *file, const char __user *buffer,
542                                    size_t count, loff_t *off)
543 {
544         struct seq_file *m = file->private_data;
545         struct lu_client_seq *seq = m->private;
546         u64 val;
547         u64 max;
548         int rc;
549
550         ENTRY;
551         LASSERT(seq != NULL);
552
553         mutex_lock(&seq->lcs_mutex);
554
555         rc = kstrtoull_from_user(buffer, count, 0, &val);
556         if (rc) {
557                 GOTO(out_unlock, count = rc);
558         }
559
560         if (seq->lcs_type == LUSTRE_SEQ_DATA)
561                 max = LUSTRE_DATA_SEQ_MAX_WIDTH;
562         else
563                 max = LUSTRE_METADATA_SEQ_MAX_WIDTH;
564
565         if (val <= max) {
566                 seq->lcs_width = val;
567
568                 CDEBUG(D_INFO, "%s: Sequence size: %llu\n",
569                        seq->lcs_name, seq->lcs_width);
570         } else {
571                 GOTO(out_unlock, count = -ERANGE);
572         }
573
574 out_unlock:
575         mutex_unlock(&seq->lcs_mutex);
576         RETURN(count);
577 }
578
579 static int
580 lprocfs_client_fid_width_seq_show(struct seq_file *m, void *unused)
581 {
582         struct lu_client_seq *seq = (struct lu_client_seq *)m->private;
583         ENTRY;
584
585         LASSERT(seq != NULL);
586
587         mutex_lock(&seq->lcs_mutex);
588         seq_printf(m, "%llu\n", seq->lcs_width);
589         mutex_unlock(&seq->lcs_mutex);
590
591         RETURN(0);
592 }
593
594 static int
595 lprocfs_client_fid_fid_seq_show(struct seq_file *m, void *unused)
596 {
597         struct lu_client_seq *seq = (struct lu_client_seq *)m->private;
598         ENTRY;
599
600         LASSERT(seq != NULL);
601
602         mutex_lock(&seq->lcs_mutex);
603         seq_printf(m, DFID"\n", PFID(&seq->lcs_fid));
604         mutex_unlock(&seq->lcs_mutex);
605
606         RETURN(0);
607 }
608
609 static int
610 lprocfs_client_fid_server_seq_show(struct seq_file *m, void *unused)
611 {
612         struct lu_client_seq *seq = (struct lu_client_seq *)m->private;
613         struct client_obd *cli;
614         ENTRY;
615
616         LASSERT(seq != NULL);
617
618         if (seq->lcs_exp != NULL) {
619                 cli = &seq->lcs_exp->exp_obd->u.cli;
620                 seq_printf(m, "%s\n", cli->cl_target_uuid.uuid);
621         } else {
622                 seq_printf(m, "%s\n", seq->lcs_srv->lss_name);
623         }
624         RETURN(0);
625 }
626
627 LPROC_SEQ_FOPS(lprocfs_client_fid_space);
628 LPROC_SEQ_FOPS(lprocfs_client_fid_width);
629 LPROC_SEQ_FOPS_RO(lprocfs_client_fid_server);
630 LPROC_SEQ_FOPS_RO(lprocfs_client_fid_fid);
631
632 struct lprocfs_vars seq_client_proc_list[] = {
633         { .name =       "space",
634           .fops =       &lprocfs_client_fid_space_fops  },
635         { .name =       "width",
636           .fops =       &lprocfs_client_fid_width_fops  },
637         { .name =       "server",
638           .fops =       &lprocfs_client_fid_server_fops },
639         { .name =       "fid",
640           .fops =       &lprocfs_client_fid_fid_fops    },
641         { NULL }
642 };
643
644 #endif /* CONFIG_PROC_FS */