Whamcloud - gitweb
9561391faca3d738e95927f8903e7aeb79fee4db
[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, 2014, 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 LPROCFS
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 (!range_is_sane(&tmp) || 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         int rc;
131         ENTRY;
132
133         LASSERT(seq != NULL);
134
135         mutex_lock(&seq->lss_mutex);
136         rc = seq_printf(m, "["LPX64" - "LPX64"]:%x:%s\n",
137                         PRANGE(&seq->lss_space));
138         mutex_unlock(&seq->lss_mutex);
139
140         RETURN(rc);
141 }
142
143 static int
144 lprocfs_server_fid_server_seq_show(struct seq_file *m, void *unused)
145 {
146         struct lu_server_seq *seq = (struct lu_server_seq *)m->private;
147         struct client_obd *cli;
148         int rc;
149         ENTRY;
150
151         LASSERT(seq != NULL);
152
153         if (seq->lss_cli) {
154                 if (seq->lss_cli->lcs_exp != NULL) {
155                         cli = &seq->lss_cli->lcs_exp->exp_obd->u.cli;
156                         rc = seq_printf(m, "%s\n", cli->cl_target_uuid.uuid);
157                 } else {
158                         rc = seq_printf(m, "%s\n",
159                                         seq->lss_cli->lcs_srv->lss_name);
160                 }
161         } else {
162                 rc = seq_printf(m, "<none>\n");
163         }
164
165         RETURN(rc);
166 }
167
168 static ssize_t
169 lprocfs_server_fid_width_seq_write(struct file *file, const char __user *buffer,
170                                         size_t count, loff_t *off)
171 {
172         struct lu_server_seq *seq = ((struct seq_file *)file->private_data)->private;
173         int rc, val;
174         ENTRY;
175
176         LASSERT(seq != NULL);
177
178         mutex_lock(&seq->lss_mutex);
179
180         rc = lprocfs_write_helper(buffer, count, &val);
181         if (rc != 0) {
182                 CERROR("%s: invalid width.\n", seq->lss_name);
183                 GOTO(out_unlock, count = rc);
184         }
185
186         seq->lss_width = val;
187
188         CDEBUG(D_INFO, "%s: Width: "LPU64"\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         int rc;
201         ENTRY;
202
203         LASSERT(seq != NULL);
204
205         mutex_lock(&seq->lss_mutex);
206         rc = seq_printf(m, LPU64"\n", seq->lss_width);
207         mutex_unlock(&seq->lss_mutex);
208
209         RETURN(rc);
210 }
211
212 LPROC_SEQ_FOPS(lprocfs_server_fid_space);
213 LPROC_SEQ_FOPS(lprocfs_server_fid_width);
214 LPROC_SEQ_FOPS_RO(lprocfs_server_fid_server);
215
216 struct lprocfs_seq_vars seq_server_proc_list[] = {
217         { .name =       "space",
218           .fops =       &lprocfs_server_fid_space_fops  },
219         { .name =       "width",
220           .fops =       &lprocfs_server_fid_width_fops  },
221         { .name =       "server",
222           .fops =       &lprocfs_server_fid_server_fops },
223         { NULL }
224 };
225
226 struct fld_seq_param {
227         struct lu_env           fsp_env;
228         struct dt_it            *fsp_it;
229         struct lu_server_fld    *fsp_fld;
230         struct lu_server_seq    *fsp_seq;
231         unsigned int            fsp_stop:1;
232 };
233
234 /*
235  * XXX: below is a copy of the functions in lustre/fld/lproc_fld.c.
236  * we want to avoid this duplication either by exporting the
237  * functions or merging fid and fld into a single module.
238  */
239 static void *fldb_seq_start(struct seq_file *p, loff_t *pos)
240 {
241         struct fld_seq_param    *param = p->private;
242         struct lu_server_fld    *fld;
243         struct dt_object        *obj;
244         const struct dt_it_ops  *iops;
245         struct dt_key           *key;
246         int                     rc;
247
248         if (param == NULL || param->fsp_stop)
249                 return NULL;
250
251         fld = param->fsp_fld;
252         obj = fld->lsf_obj;
253         LASSERT(obj != NULL);
254         iops = &obj->do_index_ops->dio_it;
255
256         rc = iops->load(&param->fsp_env, param->fsp_it, *pos);
257         if (rc <= 0)
258                 return NULL;
259
260         key = iops->key(&param->fsp_env, param->fsp_it);
261         if (IS_ERR(key))
262                 return NULL;
263
264         *pos = be64_to_cpu(*(__u64 *)key);
265
266         return param;
267 }
268
269 static void fldb_seq_stop(struct seq_file *p, void *v)
270 {
271         struct fld_seq_param    *param = p->private;
272         const struct dt_it_ops  *iops;
273         struct lu_server_fld    *fld;
274         struct dt_object        *obj;
275
276         if (param == NULL)
277                 return;
278
279         fld = param->fsp_fld;
280         obj = fld->lsf_obj;
281         LASSERT(obj != NULL);
282         iops = &obj->do_index_ops->dio_it;
283
284         iops->put(&param->fsp_env, param->fsp_it);
285 }
286
287 static void *fldb_seq_next(struct seq_file *p, void *v, loff_t *pos)
288 {
289         struct fld_seq_param    *param = p->private;
290         struct lu_server_fld    *fld;
291         struct dt_object        *obj;
292         const struct dt_it_ops  *iops;
293         int                     rc;
294
295         if (param == NULL || param->fsp_stop)
296                 return NULL;
297
298         fld = param->fsp_fld;
299         obj = fld->lsf_obj;
300         LASSERT(obj != NULL);
301         iops = &obj->do_index_ops->dio_it;
302
303         rc = iops->next(&param->fsp_env, param->fsp_it);
304         if (rc > 0) {
305                 param->fsp_stop = 1;
306                 return NULL;
307         }
308
309         *pos = be64_to_cpu(*(__u64 *)iops->key(&param->fsp_env, param->fsp_it));
310         return param;
311 }
312
313 static int fldb_seq_show(struct seq_file *p, void *v)
314 {
315         struct fld_seq_param    *param = p->private;
316         struct lu_server_fld    *fld;
317         struct dt_object        *obj;
318         const struct dt_it_ops  *iops;
319         struct lu_seq_range      fld_rec;
320         int                     rc;
321
322         if (param == NULL || param->fsp_stop)
323                 return 0;
324
325         fld = param->fsp_fld;
326         obj = fld->lsf_obj;
327         LASSERT(obj != NULL);
328         iops = &obj->do_index_ops->dio_it;
329
330         rc = iops->rec(&param->fsp_env, param->fsp_it,
331                        (struct dt_rec *)&fld_rec, 0);
332         if (rc != 0) {
333                 CERROR("%s: read record error: rc = %d\n",
334                        fld->lsf_name, rc);
335         } else if (fld_rec.lsr_start != 0) {
336                 range_be_to_cpu(&fld_rec, &fld_rec);
337                 rc = seq_printf(p, DRANGE"\n", PRANGE(&fld_rec));
338         }
339
340         return rc;
341 }
342
343 struct seq_operations fldb_sops = {
344         .start = fldb_seq_start,
345         .stop = fldb_seq_stop,
346         .next = fldb_seq_next,
347         .show = fldb_seq_show,
348 };
349
350 static int fldb_seq_open(struct inode *inode, struct file *file)
351 {
352         struct seq_file         *seq;
353         struct lu_server_seq    *ss = (struct lu_server_seq *) PDE_DATA(inode);
354         struct lu_server_fld    *fld;
355         struct dt_object        *obj;
356         const struct dt_it_ops  *iops;
357         struct fld_seq_param    *param = NULL;
358         int                     env_init = 0;
359         int                     rc;
360
361         fld = ss->lss_site->ss_server_fld;
362         LASSERT(fld != NULL);
363
364         rc = LPROCFS_ENTRY_CHECK(inode);
365         if (rc < 0)
366                 return rc;
367
368         rc = seq_open(file, &fldb_sops);
369         if (rc)
370                 return rc;
371
372         obj = fld->lsf_obj;
373         if (obj == NULL) {
374                 seq = file->private_data;
375                 seq->private = NULL;
376                 return 0;
377         }
378
379         OBD_ALLOC_PTR(param);
380         if (param == NULL)
381                 GOTO(out, rc = -ENOMEM);
382
383         rc = lu_env_init(&param->fsp_env, LCT_MD_THREAD);
384         if (rc != 0)
385                 GOTO(out, rc);
386
387         env_init = 1;
388         iops = &obj->do_index_ops->dio_it;
389         param->fsp_it = iops->init(&param->fsp_env, obj, 0, NULL);
390         if (IS_ERR(param->fsp_it))
391                 GOTO(out, rc = PTR_ERR(param->fsp_it));
392
393         param->fsp_fld = fld;
394         param->fsp_seq = ss;
395         param->fsp_stop = 0;
396
397         seq = file->private_data;
398         seq->private = param;
399 out:
400         if (rc != 0) {
401                 if (env_init == 1)
402                         lu_env_fini(&param->fsp_env);
403                 if (param != NULL)
404                         OBD_FREE_PTR(param);
405         }
406         return rc;
407 }
408
409 static int fldb_seq_release(struct inode *inode, struct file *file)
410 {
411         struct seq_file         *seq = file->private_data;
412         struct fld_seq_param    *param;
413         struct lu_server_fld    *fld;
414         struct dt_object        *obj;
415         const struct dt_it_ops  *iops;
416
417         param = seq->private;
418         if (param == NULL) {
419                 lprocfs_seq_release(inode, file);
420                 return 0;
421         }
422
423         fld = param->fsp_fld;
424         obj = fld->lsf_obj;
425         LASSERT(obj != NULL);
426         iops = &obj->do_index_ops->dio_it;
427
428         LASSERT(iops != NULL);
429         LASSERT(param->fsp_it != NULL);
430         iops->fini(&param->fsp_env, param->fsp_it);
431         lu_env_fini(&param->fsp_env);
432         OBD_FREE_PTR(param);
433         lprocfs_seq_release(inode, file);
434
435         return 0;
436 }
437
438 static ssize_t fldb_seq_write(struct file *file, const char __user *buf,
439                               size_t len, loff_t *off)
440 {
441         struct seq_file         *seq = file->private_data;
442         struct fld_seq_param    *param;
443         struct lu_seq_range      range;
444         int                      rc = 0;
445         char                     _buffer[MAX_FID_RANGE_STRLEN];
446         char                    *buffer = _buffer;
447         ENTRY;
448
449         param = seq->private;
450         if (param == NULL)
451                 RETURN(-EINVAL);
452
453         if (len >= sizeof(_buffer))
454                 RETURN(-EINVAL);
455
456         if (copy_from_user(buffer, buf, len))
457                 GOTO(out, rc = -EFAULT);
458         buffer[len] = 0;
459
460         /*
461          * format - [0x0000000200000007-0x0000000200000008):0:mdt
462          */
463         if (*buffer != '[')
464                 GOTO(out, rc = -EINVAL);
465         buffer++;
466
467         range.lsr_start = simple_strtoull(buffer, &buffer, 0);
468         if (*buffer != '-')
469                 GOTO(out, rc = -EINVAL);
470         buffer++;
471
472         range.lsr_end = simple_strtoull(buffer, &buffer, 0);
473         if (*buffer != ')')
474                 GOTO(out, rc = -EINVAL);
475         buffer++;
476         if (*buffer != ':')
477                 GOTO(out, rc = -EINVAL);
478         buffer++;
479
480         range.lsr_index = simple_strtoul(buffer, &buffer, 0);
481         if (*buffer != ':')
482                 GOTO(out, rc = -EINVAL);
483         buffer++;
484
485         if (strncmp(buffer, "mdt", 3) == 0)
486                 range.lsr_flags = LU_SEQ_RANGE_MDT;
487         else if (strncmp(buffer, "ost", 3) == 0)
488                 range.lsr_flags = LU_SEQ_RANGE_OST;
489         else
490                 GOTO(out, rc = -EINVAL);
491
492         rc = seq_server_alloc_spec(param->fsp_seq->lss_site->ss_control_seq,
493                                    &range, &param->fsp_env);
494
495 out:
496         RETURN(rc < 0 ? rc : len);
497 }
498
499 const struct file_operations seq_fld_proc_seq_fops = {
500         .owner   = THIS_MODULE,
501         .open    = fldb_seq_open,
502         .read    = seq_read,
503         .write   = fldb_seq_write,
504         .release = fldb_seq_release,
505 };
506
507 #endif /* HAVE_SERVER_SUPPORT */
508
509 /* Client side procfs stuff */
510 static ssize_t
511 lprocfs_client_fid_space_seq_write(struct file *file, const char __user *buffer,
512                                    size_t count, loff_t *off)
513 {
514         struct lu_client_seq *seq = ((struct seq_file *)file->private_data)->private;
515         int rc;
516         ENTRY;
517
518         LASSERT(seq != NULL);
519
520         mutex_lock(&seq->lcs_mutex);
521         rc = lprocfs_fid_write_common(buffer, count, &seq->lcs_space);
522         if (rc == 0) {
523                 CDEBUG(D_INFO, "%s: Space: "DRANGE"\n",
524                        seq->lcs_name, PRANGE(&seq->lcs_space));
525         }
526
527         mutex_unlock(&seq->lcs_mutex);
528
529         RETURN(count);
530 }
531
532 static int
533 lprocfs_client_fid_space_seq_show(struct seq_file *m, void *unused)
534 {
535         struct lu_client_seq *seq = (struct lu_client_seq *)m->private;
536         int rc;
537         ENTRY;
538
539         LASSERT(seq != NULL);
540
541         mutex_lock(&seq->lcs_mutex);
542         rc = seq_printf(m, "["LPX64" - "LPX64"]:%x:%s\n",
543                         PRANGE(&seq->lcs_space));
544         mutex_unlock(&seq->lcs_mutex);
545
546         RETURN(rc);
547 }
548
549 static ssize_t
550 lprocfs_client_fid_width_seq_write(struct file *file, const char __user *buffer,
551                                    size_t count, loff_t *off)
552 {
553         struct lu_client_seq *seq = ((struct seq_file *)file->private_data)->private;
554         __u64  max;
555         int rc, val;
556         ENTRY;
557
558         LASSERT(seq != NULL);
559
560         mutex_lock(&seq->lcs_mutex);
561
562         rc = lprocfs_write_helper(buffer, count, &val);
563         if (rc) {
564                 mutex_unlock(&seq->lcs_mutex);
565                 RETURN(rc);
566         }
567
568         if (seq->lcs_type == LUSTRE_SEQ_DATA)
569                 max = LUSTRE_DATA_SEQ_MAX_WIDTH;
570         else
571                 max = LUSTRE_METADATA_SEQ_MAX_WIDTH;
572
573         if (val <= max && val > 0) {
574                 seq->lcs_width = val;
575
576                 if (rc == 0) {
577                         CDEBUG(D_INFO, "%s: Sequence size: "LPU64"\n",
578                                seq->lcs_name, seq->lcs_width);
579                 }
580         }
581         mutex_unlock(&seq->lcs_mutex);
582
583         RETURN(count);
584 }
585
586 static int
587 lprocfs_client_fid_width_seq_show(struct seq_file *m, void *unused)
588 {
589         struct lu_client_seq *seq = (struct lu_client_seq *)m->private;
590         int rc;
591         ENTRY;
592
593         LASSERT(seq != NULL);
594
595         mutex_lock(&seq->lcs_mutex);
596         rc = seq_printf(m, LPU64"\n", seq->lcs_width);
597         mutex_unlock(&seq->lcs_mutex);
598
599         RETURN(rc);
600 }
601
602 static int
603 lprocfs_client_fid_fid_seq_show(struct seq_file *m, void *unused)
604 {
605         struct lu_client_seq *seq = (struct lu_client_seq *)m->private;
606         int rc;
607         ENTRY;
608
609         LASSERT(seq != NULL);
610
611         mutex_lock(&seq->lcs_mutex);
612         rc = seq_printf(m, DFID"\n", PFID(&seq->lcs_fid));
613         mutex_unlock(&seq->lcs_mutex);
614
615         RETURN(rc);
616 }
617
618 static int
619 lprocfs_client_fid_server_seq_show(struct seq_file *m, void *unused)
620 {
621         struct lu_client_seq *seq = (struct lu_client_seq *)m->private;
622         struct client_obd *cli;
623         int rc;
624         ENTRY;
625
626         LASSERT(seq != NULL);
627
628         if (seq->lcs_exp != NULL) {
629                 cli = &seq->lcs_exp->exp_obd->u.cli;
630                 rc = seq_printf(m, "%s\n", cli->cl_target_uuid.uuid);
631         } else {
632                 rc = seq_printf(m, "%s\n", seq->lcs_srv->lss_name);
633         }
634         RETURN(rc);
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_seq_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 #endif