Whamcloud - gitweb
LU-3565 mdt: a new param to allocate sequences
[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, 2013, 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 #include <md_object.h>
54
55 #ifdef LPROCFS
56 /*
57  * Note: this function is only used for testing, it is no safe for production
58  * use.
59  */
60 static int
61 seq_proc_write_common(struct file *file, const char *buffer,
62                       unsigned long count, void *data,
63                       struct lu_seq_range *range)
64 {
65         struct lu_seq_range tmp;
66         int rc;
67         ENTRY;
68
69         LASSERT(range != NULL);
70
71         if (count == 5 && strcmp(buffer, "clear") == 0) {
72                 memset(range, 0, sizeof(*range));
73                 RETURN(0);
74         }
75
76         rc = sscanf(buffer, "[%llx - %llx]\n",
77                     (long long unsigned *)&tmp.lsr_start,
78                     (long long unsigned *)&tmp.lsr_end);
79         if (rc != 2 || !range_is_sane(&tmp) || range_is_zero(&tmp))
80                 RETURN(-EINVAL);
81         *range = tmp;
82         RETURN(0);
83 }
84
85 static int
86 seq_proc_read_common(char *page, char **start, off_t off,
87                      int count, int *eof, void *data,
88                      struct lu_seq_range *range)
89 {
90         int rc;
91         ENTRY;
92
93         *eof = 1;
94         rc = snprintf(page, count, "["LPX64" - "LPX64"]:%x:%s\n",
95                         PRANGE(range));
96         RETURN(rc);
97 }
98
99 #ifdef HAVE_SERVER_SUPPORT
100 /*
101  * Server side procfs stuff.
102  */
103 static int
104 seq_server_proc_write_space(struct file *file, const char *buffer,
105                             unsigned long count, void *data)
106 {
107         struct lu_server_seq *seq = (struct lu_server_seq *)data;
108         int rc;
109         ENTRY;
110
111         LASSERT(seq != NULL);
112
113         mutex_lock(&seq->lss_mutex);
114         rc = seq_proc_write_common(file, buffer, count,
115                                    data, &seq->lss_space);
116         if (rc == 0) {
117                 CDEBUG(D_INFO, "%s: Space: "DRANGE"\n",
118                        seq->lss_name, PRANGE(&seq->lss_space));
119         }
120
121         mutex_unlock(&seq->lss_mutex);
122
123         RETURN(count);
124 }
125
126 static int
127 seq_server_proc_read_space(char *page, char **start, off_t off,
128                            int count, int *eof, void *data)
129 {
130         struct lu_server_seq *seq = (struct lu_server_seq *)data;
131         int rc;
132         ENTRY;
133
134         LASSERT(seq != NULL);
135
136         mutex_lock(&seq->lss_mutex);
137         rc = seq_proc_read_common(page, start, off, count, eof,
138                                   data, &seq->lss_space);
139         mutex_unlock(&seq->lss_mutex);
140
141         RETURN(rc);
142 }
143
144 static int
145 seq_server_proc_read_server(char *page, char **start, off_t off,
146                             int count, int *eof, void *data)
147 {
148         struct lu_server_seq *seq = (struct lu_server_seq *)data;
149         struct client_obd *cli;
150         int rc;
151         ENTRY;
152
153         LASSERT(seq != NULL);
154
155         *eof = 1;
156         if (seq->lss_cli) {
157                 if (seq->lss_cli->lcs_exp != NULL) {
158                         cli = &seq->lss_cli->lcs_exp->exp_obd->u.cli;
159                         rc = snprintf(page, count, "%s\n",
160                                       cli->cl_target_uuid.uuid);
161                 } else {
162                         rc = snprintf(page, count, "%s\n",
163                                       seq->lss_cli->lcs_srv->lss_name);
164                 }
165         } else {
166                 rc = snprintf(page, count, "<none>\n");
167         }
168
169         RETURN(rc);
170 }
171
172 static int
173 seq_server_proc_write_width(struct file *file, const char *buffer,
174                             unsigned long count, void *data)
175 {
176         struct lu_server_seq *seq = (struct lu_server_seq *)data;
177         int rc, val;
178         ENTRY;
179
180         LASSERT(seq != NULL);
181
182         mutex_lock(&seq->lss_mutex);
183
184         rc = lprocfs_write_helper(buffer, count, &val);
185         if (rc != 0) {
186                 CERROR("%s: invalid width.\n", seq->lss_name);
187                 GOTO(out_unlock, rc);
188         }
189
190         seq->lss_width = val;
191
192         CDEBUG(D_INFO, "%s: Width: "LPU64"\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 seq_server_proc_read_width(char *page, char **start, off_t off,
202                            int count, int *eof, void *data)
203 {
204         struct lu_server_seq *seq = (struct lu_server_seq *)data;
205         int rc;
206         ENTRY;
207
208         LASSERT(seq != NULL);
209
210         mutex_lock(&seq->lss_mutex);
211         rc = snprintf(page, count, LPU64"\n", seq->lss_width);
212         mutex_unlock(&seq->lss_mutex);
213
214         RETURN(rc);
215 }
216
217 struct lprocfs_vars seq_server_proc_list[] = {
218         { "space",
219           seq_server_proc_read_space, seq_server_proc_write_space, NULL },
220         { "width",
221           seq_server_proc_read_width, seq_server_proc_write_width, NULL },
222         { "server",
223           seq_server_proc_read_server, NULL, NULL },
224         { NULL }
225 };
226
227 struct fld_seq_param {
228         struct lu_env           fsp_env;
229         struct dt_it            *fsp_it;
230         struct lu_server_fld    *fsp_fld;
231         struct lu_server_seq    *fsp_seq;
232         unsigned int            fsp_stop:1;
233 };
234
235 /*
236  * XXX: below is a copy of the functions in lustre/fld/lproc_fld.c.
237  * we want to avoid this duplication either by exporting the
238  * functions or merging fid and fld into a single module.
239  */
240 static void *fldb_seq_start(struct seq_file *p, loff_t *pos)
241 {
242         struct fld_seq_param    *param = p->private;
243         struct lu_server_fld    *fld;
244         struct dt_object        *obj;
245         const struct dt_it_ops  *iops;
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         iops->load(&param->fsp_env, param->fsp_it, *pos);
256
257         *pos = be64_to_cpu(*(__u64 *)iops->key(&param->fsp_env, param->fsp_it));
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                 rc = 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 proc_dir_entry   *dp = PDE(inode);
345         struct seq_file         *seq;
346         struct lu_server_seq    *ss = (struct lu_server_seq *)dp->data;
347         struct lu_server_fld    *fld;
348         struct dt_object        *obj;
349         const struct dt_it_ops  *iops;
350         struct fld_seq_param    *param = NULL;
351         int                     env_init = 0;
352         int                     rc;
353
354         fld = ss->lss_site->ss_server_fld;
355         LASSERT(fld != NULL);
356
357         LPROCFS_ENTRY_AND_CHECK(dp);
358         rc = seq_open(file, &fldb_sops);
359         if (rc)
360                 GOTO(out, rc);
361
362         obj = fld->lsf_obj;
363         if (obj == NULL) {
364                 seq = file->private_data;
365                 seq->private = NULL;
366                 return 0;
367         }
368
369         OBD_ALLOC_PTR(param);
370         if (param == NULL)
371                 GOTO(out, rc = -ENOMEM);
372
373         rc = lu_env_init(&param->fsp_env, LCT_MD_THREAD);
374         if (rc != 0)
375                 GOTO(out, rc);
376
377         env_init = 1;
378         iops = &obj->do_index_ops->dio_it;
379         param->fsp_it = iops->init(&param->fsp_env, obj, 0, NULL);
380         if (IS_ERR(param->fsp_it))
381                 GOTO(out, rc = PTR_ERR(param->fsp_it));
382
383         param->fsp_fld = fld;
384         param->fsp_seq = ss;
385         param->fsp_stop = 0;
386
387         seq = file->private_data;
388         seq->private = param;
389 out:
390         if (rc != 0) {
391                 if (env_init == 1)
392                         lu_env_fini(&param->fsp_env);
393                 if (param != NULL)
394                         OBD_FREE_PTR(param);
395                 LPROCFS_EXIT();
396         }
397         return rc;
398 }
399
400 static int fldb_seq_release(struct inode *inode, struct file *file)
401 {
402         struct seq_file         *seq = file->private_data;
403         struct fld_seq_param    *param;
404         struct lu_server_fld    *fld;
405         struct dt_object        *obj;
406         const struct dt_it_ops  *iops;
407
408         param = seq->private;
409         if (param == NULL) {
410                 lprocfs_seq_release(inode, file);
411                 return 0;
412         }
413
414         fld = param->fsp_fld;
415         obj = fld->lsf_obj;
416         LASSERT(obj != NULL);
417         iops = &obj->do_index_ops->dio_it;
418
419         LASSERT(iops != NULL);
420         LASSERT(obj != 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 *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, *_buffer;
438         ENTRY;
439
440         param = seq->private;
441         if (param == NULL)
442                 RETURN(-EINVAL);
443
444         OBD_ALLOC(buffer, len + 1);
445         if (buffer == NULL)
446                 RETURN(-ENOMEM);
447         memcpy(buffer, buf, len);
448         buffer[len] = 0;
449         _buffer = buffer;
450
451         /*
452          * format - [0x0000000200000007-0x0000000200000008):0:mdt
453          */
454         if (*buffer != '[')
455                 GOTO(out, rc = -EINVAL);
456         buffer++;
457
458         range.lsr_start = simple_strtoull(buffer, &buffer, 0);
459         if (*buffer != '-')
460                 GOTO(out, rc = -EINVAL);
461         buffer++;
462
463         range.lsr_end = simple_strtoull(buffer, &buffer, 0);
464         if (*buffer != ')')
465                 GOTO(out, rc = -EINVAL);
466         buffer++;
467         if (*buffer != ':')
468                 GOTO(out, rc = -EINVAL);
469         buffer++;
470
471         range.lsr_index = simple_strtoul(buffer, &buffer, 0);
472         if (*buffer != ':')
473                 GOTO(out, rc = -EINVAL);
474         buffer++;
475
476         if (strncmp(buffer, "mdt", 3) == 0)
477                 range.lsr_flags = LU_SEQ_RANGE_MDT;
478         else if (strncmp(buffer, "ost", 3) == 0)
479                 range.lsr_flags = LU_SEQ_RANGE_OST;
480         else
481                 GOTO(out, rc = -EINVAL);
482
483         rc = seq_server_alloc_spec(param->fsp_seq->lss_site->ss_control_seq,
484                                    &range, &param->fsp_env);
485
486 out:
487         OBD_FREE(_buffer, len + 1);
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 int
503 seq_client_proc_write_space(struct file *file, const char *buffer,
504                             unsigned long count, void *data)
505 {
506         struct lu_client_seq *seq = (struct lu_client_seq *)data;
507         int rc;
508         ENTRY;
509
510         LASSERT(seq != NULL);
511
512         mutex_lock(&seq->lcs_mutex);
513         rc = seq_proc_write_common(file, buffer, count,
514                                    data, &seq->lcs_space);
515
516         if (rc == 0) {
517                 CDEBUG(D_INFO, "%s: Space: "DRANGE"\n",
518                        seq->lcs_name, PRANGE(&seq->lcs_space));
519         }
520
521         mutex_unlock(&seq->lcs_mutex);
522
523         RETURN(count);
524 }
525
526 static int
527 seq_client_proc_read_space(char *page, char **start, off_t off,
528                            int count, int *eof, void *data)
529 {
530         struct lu_client_seq *seq = (struct lu_client_seq *)data;
531         int rc;
532         ENTRY;
533
534         LASSERT(seq != NULL);
535
536         mutex_lock(&seq->lcs_mutex);
537         rc = seq_proc_read_common(page, start, off, count, eof,
538                                   data, &seq->lcs_space);
539         mutex_unlock(&seq->lcs_mutex);
540
541         RETURN(rc);
542 }
543
544 static int
545 seq_client_proc_write_width(struct file *file, const char *buffer,
546                             unsigned long count, void *data)
547 {
548         struct lu_client_seq *seq = (struct lu_client_seq *)data;
549         __u64  max;
550         int rc, val;
551         ENTRY;
552
553         LASSERT(seq != NULL);
554
555         mutex_lock(&seq->lcs_mutex);
556
557         rc = lprocfs_write_helper(buffer, count, &val);
558         if (rc) {
559                 mutex_unlock(&seq->lcs_mutex);
560                 RETURN(rc);
561         }
562
563         if (seq->lcs_type == LUSTRE_SEQ_DATA)
564                 max = LUSTRE_DATA_SEQ_MAX_WIDTH;
565         else
566                 max = LUSTRE_METADATA_SEQ_MAX_WIDTH;
567
568         if (val <= max && val > 0) {
569                 seq->lcs_width = val;
570
571                 if (rc == 0) {
572                         CDEBUG(D_INFO, "%s: Sequence size: "LPU64"\n",
573                                seq->lcs_name, seq->lcs_width);
574                 }
575         }
576
577         mutex_unlock(&seq->lcs_mutex);
578
579         RETURN(count);
580 }
581
582 static int
583 seq_client_proc_read_width(char *page, char **start, off_t off,
584                            int count, int *eof, void *data)
585 {
586         struct lu_client_seq *seq = (struct lu_client_seq *)data;
587         int rc;
588         ENTRY;
589
590         LASSERT(seq != NULL);
591
592         mutex_lock(&seq->lcs_mutex);
593         rc = snprintf(page, count, LPU64"\n", seq->lcs_width);
594         mutex_unlock(&seq->lcs_mutex);
595
596         RETURN(rc);
597 }
598
599 static int
600 seq_client_proc_read_fid(char *page, char **start, off_t off,
601                          int count, int *eof, void *data)
602 {
603         struct lu_client_seq *seq = (struct lu_client_seq *)data;
604         int rc;
605         ENTRY;
606
607         LASSERT(seq != NULL);
608
609         mutex_lock(&seq->lcs_mutex);
610         rc = snprintf(page, count, DFID"\n", PFID(&seq->lcs_fid));
611         mutex_unlock(&seq->lcs_mutex);
612
613         RETURN(rc);
614 }
615
616 static int
617 seq_client_proc_read_server(char *page, char **start, off_t off,
618                             int count, int *eof, void *data)
619 {
620         struct lu_client_seq *seq = (struct lu_client_seq *)data;
621         struct client_obd *cli;
622         int rc;
623         ENTRY;
624
625         LASSERT(seq != NULL);
626
627         if (seq->lcs_exp != NULL) {
628                 cli = &seq->lcs_exp->exp_obd->u.cli;
629                 rc = snprintf(page, count, "%s\n", cli->cl_target_uuid.uuid);
630         } else {
631                 rc = snprintf(page, count, "%s\n", seq->lcs_srv->lss_name);
632         }
633         RETURN(rc);
634 }
635
636 struct lprocfs_vars seq_client_proc_list[] = {
637         { "space",    seq_client_proc_read_space, seq_client_proc_write_space, NULL },
638         { "width",    seq_client_proc_read_width, seq_client_proc_write_width, NULL },
639         { "server",   seq_client_proc_read_server, NULL, NULL },
640         { "fid",      seq_client_proc_read_fid, NULL, NULL },
641         { NULL }};
642 #endif