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