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