Whamcloud - gitweb
LU-2363 lod: Fix statfs entries in lod procfs
[fs/lustre-release.git] / lustre / lod / lproc_lod.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  2008 Sun Microsystems, Inc. All rights reserved
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2011,2012 Whamcloud, Inc.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  */
36 #define DEBUG_SUBSYSTEM S_CLASS
37
38 #include <lprocfs_status.h>
39 #include <obd_class.h>
40 #include <linux/seq_file.h>
41 #include "lod_internal.h"
42 #include <lustre_param.h>
43
44 #ifdef LPROCFS
45 static int lod_rd_stripesize(char *page, char **start, off_t off, int count,
46                              int *eof, void *data)
47 {
48         struct obd_device *dev  = (struct obd_device *)data;
49         struct lod_device *lod;
50
51         LASSERT(dev != NULL);
52         lod  = lu2lod_dev(dev->obd_lu_dev);
53         *eof = 1;
54         return snprintf(page, count, LPU64"\n",
55                         lod->lod_desc.ld_default_stripe_size);
56 }
57
58 static int lod_wr_stripesize(struct file *file, const char *buffer,
59                              unsigned long count, void *data)
60 {
61         struct obd_device *dev = (struct obd_device *)data;
62         struct lod_device *lod;
63         __u64 val;
64         int rc;
65
66         LASSERT(dev != NULL);
67         lod  = lu2lod_dev(dev->obd_lu_dev);
68         rc = lprocfs_write_u64_helper(buffer, count, &val);
69         if (rc)
70                 return rc;
71
72         lod_fix_desc_stripe_size(&val);
73         lod->lod_desc.ld_default_stripe_size = val;
74         return count;
75 }
76
77 static int lod_rd_stripeoffset(char *page, char **start, off_t off, int count,
78                                int *eof, void *data)
79 {
80         struct obd_device *dev = (struct obd_device *)data;
81         struct lod_device *lod;
82
83         LASSERT(dev != NULL);
84         lod  = lu2lod_dev(dev->obd_lu_dev);
85         *eof = 1;
86         return snprintf(page, count, LPU64"\n",
87                         lod->lod_desc.ld_default_stripe_offset);
88 }
89
90 static int lod_wr_stripeoffset(struct file *file, const char *buffer,
91                                unsigned long count, void *data)
92 {
93         struct obd_device *dev = (struct obd_device *)data;
94         struct lod_device *lod;
95         __u64 val;
96         int rc;
97
98         LASSERT(dev != NULL);
99         lod  = lu2lod_dev(dev->obd_lu_dev);
100         rc = lprocfs_write_u64_helper(buffer, count, &val);
101         if (rc)
102                 return rc;
103
104         lod->lod_desc.ld_default_stripe_offset = val;
105         return count;
106 }
107
108 static int lod_rd_stripetype(char *page, char **start, off_t off, int count,
109                              int *eof, void *data)
110 {
111         struct obd_device *dev = (struct obd_device *)data;
112         struct lod_device *lod;
113
114         LASSERT(dev != NULL);
115         lod  = lu2lod_dev(dev->obd_lu_dev);
116         *eof = 1;
117         return snprintf(page, count, "%u\n", lod->lod_desc.ld_pattern);
118 }
119
120 static int lod_wr_stripetype(struct file *file, const char *buffer,
121                              unsigned long count, void *data)
122 {
123         struct obd_device *dev = (struct obd_device *)data;
124         struct lod_device *lod;
125         int val, rc;
126
127         LASSERT(dev != NULL);
128         lod  = lu2lod_dev(dev->obd_lu_dev);
129         rc = lprocfs_write_helper(buffer, count, &val);
130         if (rc)
131                 return rc;
132
133         lod_fix_desc_pattern(&val);
134         lod->lod_desc.ld_pattern = val;
135         return count;
136 }
137
138 static int lod_rd_stripecount(char *page, char **start, off_t off, int count,
139                               int *eof, void *data)
140 {
141         struct obd_device *dev = (struct obd_device *)data;
142         struct lod_device *lod;
143
144         LASSERT(dev != NULL);
145         lod  = lu2lod_dev(dev->obd_lu_dev);
146         *eof = 1;
147         return snprintf(page, count, "%d\n",
148                         (__s16)(lod->lod_desc.ld_default_stripe_count + 1) - 1);
149 }
150
151 static int lod_wr_stripecount(struct file *file, const char *buffer,
152                               unsigned long count, void *data)
153 {
154         struct obd_device *dev = (struct obd_device *)data;
155         struct lod_device *lod;
156         int val, rc;
157
158         LASSERT(dev != NULL);
159         lod  = lu2lod_dev(dev->obd_lu_dev);
160         rc = lprocfs_write_helper(buffer, count, &val);
161         if (rc)
162                 return rc;
163
164         lod_fix_desc_stripe_count(&val);
165         lod->lod_desc.ld_default_stripe_count = val;
166         return count;
167 }
168
169 static int lod_rd_numobd(char *page, char **start, off_t off, int count,
170                          int *eof, void *data)
171 {
172         struct obd_device *dev = (struct obd_device*)data;
173         struct lod_device *lod;
174
175         LASSERT(dev != NULL);
176         lod  = lu2lod_dev(dev->obd_lu_dev);
177         *eof = 1;
178         return snprintf(page, count, "%u\n", lod->lod_desc.ld_tgt_count);
179
180 }
181
182 static int lod_rd_activeobd(char *page, char **start, off_t off, int count,
183                             int *eof, void *data)
184 {
185         struct obd_device* dev = (struct obd_device*)data;
186         struct lod_device *lod;
187
188         LASSERT(dev != NULL);
189         lod  = lu2lod_dev(dev->obd_lu_dev);
190         *eof = 1;
191         return snprintf(page, count, "%u\n",
192                         lod->lod_desc.ld_active_tgt_count);
193 }
194
195 static int lod_rd_desc_uuid(char *page, char **start, off_t off, int count,
196                             int *eof, void *data)
197 {
198         struct obd_device *dev = (struct obd_device*) data;
199         struct lod_device *lod;
200
201         LASSERT(dev != NULL);
202         lod  = lu2lod_dev(dev->obd_lu_dev);
203         *eof = 1;
204         return snprintf(page, count, "%s\n", lod->lod_desc.ld_uuid.uuid);
205 }
206
207 /* free priority (0-255): how badly user wants to choose empty osts */
208 static int lod_rd_qos_priofree(char *page, char **start, off_t off, int count,
209                                int *eof, void *data)
210 {
211         struct obd_device *dev = (struct obd_device*) data;
212         struct lod_device *lod = lu2lod_dev(dev->obd_lu_dev);
213
214         LASSERT(lod != NULL);
215         *eof = 1;
216         return snprintf(page, count, "%d%%\n",
217                         (lod->lod_qos.lq_prio_free * 100 + 255) >> 8);
218 }
219
220 static int lod_wr_qos_priofree(struct file *file, const char *buffer,
221                                unsigned long count, void *data)
222 {
223         struct obd_device *dev = (struct obd_device *)data;
224         struct lod_device *lod;
225         int val, rc;
226
227         LASSERT(dev != NULL);
228         lod = lu2lod_dev(dev->obd_lu_dev);
229
230         rc = lprocfs_write_helper(buffer, count, &val);
231         if (rc)
232                 return rc;
233
234         if (val > 100)
235                 return -EINVAL;
236         lod->lod_qos.lq_prio_free = (val << 8) / 100;
237         lod->lod_qos.lq_dirty = 1;
238         lod->lod_qos.lq_reset = 1;
239         return count;
240 }
241
242 static int lod_rd_qos_thresholdrr(char *page, char **start, off_t off,
243                                   int count, int *eof, void *data)
244 {
245         struct obd_device *dev = (struct obd_device*) data;
246         struct lod_device *lod;
247
248         LASSERT(dev != NULL);
249         lod = lu2lod_dev(dev->obd_lu_dev);
250         *eof = 1;
251         return snprintf(page, count, "%d%%\n",
252                         (lod->lod_qos.lq_threshold_rr * 100 + 255) >> 8);
253 }
254
255 static int lod_wr_qos_thresholdrr(struct file *file, const char *buffer,
256                                   unsigned long count, void *data)
257 {
258         struct obd_device *dev = (struct obd_device *)data;
259         struct lod_device *lod;
260         int val, rc;
261
262         LASSERT(dev != NULL);
263         lod = lu2lod_dev(dev->obd_lu_dev);
264
265         rc = lprocfs_write_helper(buffer, count, &val);
266         if (rc)
267                 return rc;
268
269         if (val > 100 || val < 0)
270                 return -EINVAL;
271
272         lod->lod_qos.lq_threshold_rr = (val << 8) / 100;
273         lod->lod_qos.lq_dirty = 1;
274         return count;
275 }
276
277 static int lod_rd_qos_maxage(char *page, char **start, off_t off, int count,
278                              int *eof, void *data)
279 {
280         struct obd_device *dev = (struct obd_device*) data;
281         struct lod_device *lod;
282
283         LASSERT(dev != NULL);
284         lod = lu2lod_dev(dev->obd_lu_dev);
285         *eof = 1;
286         return snprintf(page, count, "%u Sec\n", lod->lod_desc.ld_qos_maxage);
287 }
288
289 static int lod_wr_qos_maxage(struct file *file, const char *buffer,
290                              unsigned long count, void *data)
291 {
292         struct obd_device       *dev = (struct obd_device *)data;
293         struct lustre_cfg_bufs   bufs;
294         struct lod_device       *lod;
295         struct lu_device        *next;
296         struct lustre_cfg       *lcfg;
297         char                     str[32];
298         int                      val, rc, i;
299
300         LASSERT(dev != NULL);
301         lod = lu2lod_dev(dev->obd_lu_dev);
302
303         rc = lprocfs_write_helper(buffer, count, &val);
304         if (rc)
305                 return rc;
306
307         if (val <= 0)
308                 return -EINVAL;
309         lod->lod_desc.ld_qos_maxage = val;
310
311         /*
312          * propogate the value down to OSPs
313          */
314         lustre_cfg_bufs_reset(&bufs, NULL);
315         sprintf(str, "%smaxage=%d", PARAM_OSP, val);
316         lustre_cfg_bufs_set_string(&bufs, 1, str);
317         lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
318         lod_getref(lod);
319         lod_foreach_ost(lod, i) {
320                 next = &OST_TGT(lod,i)->ltd_ost->dd_lu_dev;
321                 rc = next->ld_ops->ldo_process_config(NULL, next, lcfg);
322                 if (rc)
323                         CERROR("can't set maxage on #%d: %d\n", i, rc);
324         }
325         lod_putref(lod);
326         lustre_cfg_free(lcfg);
327
328         return count;
329 }
330
331 static void *lod_osts_seq_start(struct seq_file *p, loff_t *pos)
332 {
333         struct obd_device *dev = p->private;
334         struct lod_device *lod;
335
336         LASSERT(dev != NULL);
337         lod = lu2lod_dev(dev->obd_lu_dev);
338
339         lod_getref(lod); /* released in lod_osts_seq_stop */
340         if (*pos >= lod->lod_ost_bitmap->size)
341                 return NULL;
342
343         *pos = find_next_bit(lod->lod_ost_bitmap->data,
344                                  lod->lod_ost_bitmap->size, *pos);
345         if (*pos < lod->lod_ost_bitmap->size)
346                 return OST_TGT(lod,*pos);
347         else
348                 return NULL;
349 }
350
351 static void lod_osts_seq_stop(struct seq_file *p, void *v)
352 {
353         struct obd_device *dev = p->private;
354         struct lod_device *lod;
355
356         LASSERT(dev != NULL);
357         lod = lu2lod_dev(dev->obd_lu_dev);
358         lod_putref(lod);
359 }
360
361 static void *lod_osts_seq_next(struct seq_file *p, void *v, loff_t *pos)
362 {
363         struct obd_device *dev = p->private;
364         struct lod_device *lod = lu2lod_dev(dev->obd_lu_dev);
365
366         if (*pos >= lod->lod_ost_bitmap->size - 1)
367                 return NULL;
368
369         *pos = find_next_bit(lod->lod_ost_bitmap->data,
370                                  lod->lod_ost_bitmap->size, *pos + 1);
371         if (*pos < lod->lod_ost_bitmap->size)
372                 return OST_TGT(lod,*pos);
373         else
374                 return NULL;
375 }
376
377 static int lod_osts_seq_show(struct seq_file *p, void *v)
378 {
379         struct obd_device   *obd = p->private;
380         struct lod_ost_desc *ost_desc = v;
381         struct lod_device   *lod;
382         int                  idx, rc, active;
383         struct dt_device    *next;
384         struct obd_statfs    sfs;
385
386         LASSERT(obd->obd_lu_dev);
387         lod = lu2lod_dev(obd->obd_lu_dev);
388
389         idx = ost_desc->ltd_index;
390         next = OST_TGT(lod,idx)->ltd_ost;
391         if (next == NULL)
392                 return -EINVAL;
393
394         /* XXX: should be non-NULL env, but it's very expensive */
395         active = 1;
396         rc = dt_statfs(NULL, next, &sfs);
397         if (rc == -ENOTCONN) {
398                 active = 0;
399                 rc = 0;
400         } else if (rc)
401                 return rc;
402
403         return seq_printf(p, "%d: %s %sACTIVE\n", idx,
404                           obd_uuid2str(&ost_desc->ltd_uuid),
405                           active ? "" : "IN");
406 }
407
408 static const struct seq_operations lod_osts_sops = {
409         .start  = lod_osts_seq_start,
410         .stop   = lod_osts_seq_stop,
411         .next   = lod_osts_seq_next,
412         .show   = lod_osts_seq_show,
413 };
414
415 static int lod_osts_seq_open(struct inode *inode, struct file *file)
416 {
417         struct proc_dir_entry *dp = PDE(inode);
418         struct seq_file *seq;
419         int rc;
420
421         LPROCFS_ENTRY_AND_CHECK(dp);
422         rc = seq_open(file, &lod_osts_sops);
423         if (rc) {
424                 LPROCFS_EXIT();
425                 return rc;
426         }
427
428         seq = file->private_data;
429         seq->private = dp->data;
430         return 0;
431 }
432
433 static struct lprocfs_vars lprocfs_lod_obd_vars[] = {
434         { "uuid",         lprocfs_rd_uuid,        0, 0 },
435         { "stripesize",   lod_rd_stripesize,      lod_wr_stripesize, 0 },
436         { "stripeoffset", lod_rd_stripeoffset,    lod_wr_stripeoffset, 0 },
437         { "stripecount",  lod_rd_stripecount,     lod_wr_stripecount, 0 },
438         { "stripetype",   lod_rd_stripetype,      lod_wr_stripetype, 0 },
439         { "numobd",       lod_rd_numobd,          0, 0 },
440         { "activeobd",    lod_rd_activeobd,       0, 0 },
441         { "desc_uuid",    lod_rd_desc_uuid,       0, 0 },
442         { "qos_prio_free",lod_rd_qos_priofree,    lod_wr_qos_priofree, 0 },
443         { "qos_threshold_rr",  lod_rd_qos_thresholdrr, lod_wr_qos_thresholdrr, 0 },
444         { "qos_maxage",   lod_rd_qos_maxage,      lod_wr_qos_maxage, 0 },
445         { 0 }
446 };
447
448 static struct lprocfs_vars lprocfs_lod_osd_vars[] = {
449         { "blocksize",    lprocfs_osd_rd_blksize, 0, 0 },
450         { "kbytestotal",  lprocfs_osd_rd_kbytestotal, 0, 0 },
451         { "kbytesfree",   lprocfs_osd_rd_kbytesfree, 0, 0 },
452         { "kbytesavail",  lprocfs_osd_rd_kbytesavail, 0, 0 },
453         { "filestotal",   lprocfs_osd_rd_filestotal, 0, 0 },
454         { "filesfree",    lprocfs_osd_rd_filesfree, 0, 0 },
455         { 0 }
456 };
457
458 static struct lprocfs_vars lprocfs_lod_module_vars[] = {
459         { "num_refs",     lprocfs_rd_numrefs,     0, 0 },
460         { 0 }
461 };
462
463 void lprocfs_lod_init_vars(struct lprocfs_static_vars *lvars)
464 {
465         lvars->module_vars      = lprocfs_lod_module_vars;
466         lvars->obd_vars         = lprocfs_lod_obd_vars;
467 }
468
469 static const struct file_operations lod_proc_target_fops = {
470         .owner   = THIS_MODULE,
471         .open    = lod_osts_seq_open,
472         .read    = seq_read,
473         .llseek  = seq_lseek,
474         .release = lprocfs_seq_release,
475 };
476
477 int lod_procfs_init(struct lod_device *lod)
478 {
479         struct obd_device *obd = lod2obd(lod);
480         struct lprocfs_static_vars lvars;
481         cfs_proc_dir_entry_t *lov_proc_dir;
482         int rc;
483
484         lprocfs_lod_init_vars(&lvars);
485         rc = lprocfs_obd_setup(obd, lvars.obd_vars);
486         if (rc) {
487                 CERROR("%s: cannot setup procfs entry: %d\n",
488                        obd->obd_name, rc);
489                 RETURN(rc);
490         }
491
492         rc = lprocfs_add_vars(obd->obd_proc_entry, lprocfs_lod_osd_vars,
493                               &lod->lod_dt_dev);
494         if (rc) {
495                 CERROR("%s: cannot setup procfs entry: %d\n",
496                        obd->obd_name, rc);
497                 GOTO(out, rc);
498         }
499
500         rc = lprocfs_seq_create(obd->obd_proc_entry, "target_obd",
501                                 0444, &lod_proc_target_fops, obd);
502         if (rc) {
503                 CWARN("%s: Error adding the target_obd file %d\n",
504                       obd->obd_name, rc);
505                 GOTO(out, rc);
506         }
507
508         lod->lod_pool_proc_entry = lprocfs_register("pools",
509                                                     obd->obd_proc_entry,
510                                                     NULL, NULL);
511         if (IS_ERR(lod->lod_pool_proc_entry)) {
512                 rc = PTR_ERR(lod->lod_pool_proc_entry);
513                 lod->lod_pool_proc_entry = NULL;
514                 CWARN("%s: Failed to create pool proc file: %d\n",
515                       obd->obd_name, rc);
516                 GOTO(out, rc);
517         }
518
519         /* for compatibility we link old procfs's OSC entries to osp ones */
520         lov_proc_dir = lprocfs_srch(proc_lustre_root, "lov");
521         if (lov_proc_dir != NULL && strstr(obd->obd_name, "lov") != NULL)
522                 lod->lod_symlink = lprocfs_add_symlink(obd->obd_name,
523                                                        lov_proc_dir,
524                                                        "../lod/%s",
525                                                        obd->obd_name);
526
527         RETURN(0);
528
529 out:
530         lprocfs_obd_cleanup(obd);
531
532         return rc;
533 }
534
535 void lod_procfs_fini(struct lod_device *lod)
536 {
537         struct obd_device *obd = lod2obd(lod);
538
539         if (lod->lod_symlink != NULL)
540                 lprocfs_remove(&lod->lod_symlink);
541
542         if (lod->lod_pool_proc_entry != NULL) {
543                 lprocfs_remove(&lod->lod_pool_proc_entry);
544                 lod->lod_pool_proc_entry = NULL;
545         }
546
547         lprocfs_obd_cleanup(obd);
548 }
549
550 #endif /* LPROCFS */
551