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