Whamcloud - gitweb
LU-3097 build: fix 'no effect' errors
[fs/lustre-release.git] / lustre / mdt / mdt_lproc.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/mdt/mdt_lproc.c
37  *
38  * Author: Lai Siyao <lsy@clusterfs.com>
39  * Author: Fan Yong <fanyong@clusterfs.com>
40  */
41
42 #define DEBUG_SUBSYSTEM S_MDS
43
44 #include <linux/version.h>
45 #include <asm/statfs.h>
46
47 #include <linux/module.h>
48
49 /* LUSTRE_VERSION_CODE */
50 #include <lustre_ver.h>
51 /*
52  * struct OBD_{ALLOC,FREE}*()
53  * MDT_FAIL_CHECK
54  */
55 #include <obd_support.h>
56 /* struct obd_export */
57 #include <lustre_export.h>
58 /* struct obd_device */
59 #include <obd.h>
60 #include <obd_class.h>
61 #include <lustre_mds.h>
62 #include <lprocfs_status.h>
63 #include "mdt_internal.h"
64 #include <lnet/lib-lnet.h>
65
66 /**
67  * The rename stats output would be YAML formats, like
68  * rename_stats:
69  * - snapshot_time: 1234567890.123456
70  * - same_dir:
71  *     4kB: { samples: 1230, pct: 33, cum_pct: 45 }
72  *     8kB: { samples: 1242, pct: 33, cum_pct: 78 }
73  *     16kB: { samples: 132, pct: 3, cum_pct: 81 }
74  * - crossdir_src:
75  *     4kB: { samples: 123, pct: 33, cum_pct: 45 }
76  *     8kB: { samples: 124, pct: 33, cum_pct: 78 }
77  *     16kB: { samples: 12, pct: 3, cum_pct: 81 }
78  * - crossdir_tgt:
79  *     4kB: { samples: 123, pct: 33, cum_pct: 45 }
80  *     8kB: { samples: 124, pct: 33, cum_pct: 78 }
81  *     16kB: { samples: 12, pct: 3, cum_pct: 81 }
82  **/
83
84 #define pct(a, b) (b ? a * 100 / b : 0)
85
86 static void display_rename_stats(struct seq_file *seq, char *name,
87                                  struct obd_histogram *hist)
88 {
89         unsigned long tot, t, cum = 0;
90         int i;
91
92         tot = lprocfs_oh_sum(hist);
93         if (tot > 0)
94                 seq_printf(seq, "- %-15s\n", name);
95         /* dir size start from 4K, start i from 10(2^10) here */
96         for (i = 0; i < OBD_HIST_MAX; i++) {
97                 t = hist->oh_buckets[i];
98                 cum += t;
99                 if (cum == 0)
100                         continue;
101
102                 if (i < 10)
103                         seq_printf(seq, "%6s%d%s", " ", 1<< i, "bytes:");
104                 else if (i < 20)
105                         seq_printf(seq, "%6s%d%s", " ", 1<<(i-10), "KB:");
106                 else
107                         seq_printf(seq, "%6s%d%s", " ", 1<<(i-20), "MB:");
108
109                 seq_printf(seq, " { sample: %3lu, pct: %3lu, cum_pct: %3lu }\n",
110                            t, pct(t, tot), pct(cum, tot));
111
112                 if (cum == tot)
113                         break;
114         }
115 }
116
117 static void rename_stats_show(struct seq_file *seq,
118                               struct rename_stats *rename_stats)
119 {
120         struct timeval now;
121
122         /* this sampling races with updates */
123         do_gettimeofday(&now);
124         seq_printf(seq, "rename_stats:\n");
125         seq_printf(seq, "- %-15s %lu.%lu\n", "snapshot_time:",
126                    now.tv_sec, now.tv_usec);
127
128         display_rename_stats(seq, "same_dir",
129                              &rename_stats->hist[RENAME_SAMEDIR_SIZE]);
130         display_rename_stats(seq, "crossdir_src",
131                              &rename_stats->hist[RENAME_CROSSDIR_SRC_SIZE]);
132         display_rename_stats(seq, "crossdir_tgt",
133                              &rename_stats->hist[RENAME_CROSSDIR_TGT_SIZE]);
134 }
135
136 #undef pct
137
138 static int mdt_rename_stats_seq_show(struct seq_file *seq, void *v)
139 {
140         struct mdt_device *mdt = seq->private;
141
142         rename_stats_show(seq, &mdt->mdt_rename_stats);
143
144         return 0;
145 }
146
147 static ssize_t mdt_rename_stats_seq_write(struct file *file, const char *buf,
148                                           size_t len, loff_t *off)
149 {
150         struct seq_file *seq = file->private_data;
151         struct mdt_device *mdt = seq->private;
152         int i;
153
154         for (i = 0; i < RENAME_LAST; i++)
155                 lprocfs_oh_clear(&mdt->mdt_rename_stats.hist[i]);
156
157         return len;
158 }
159
160 LPROC_SEQ_FOPS(mdt_rename_stats);
161
162 static int lproc_mdt_attach_rename_seqstat(struct mdt_device *mdt)
163 {
164         int i;
165
166         for (i = 0; i < RENAME_LAST; i++)
167                 spin_lock_init(&mdt->mdt_rename_stats.hist[i].oh_lock);
168
169         return lprocfs_obd_seq_create(mdt2obd_dev(mdt), "rename_stats", 0644,
170                                       &mdt_rename_stats_fops, mdt);
171 }
172
173 void mdt_rename_counter_tally(struct mdt_thread_info *info,
174                               struct mdt_device *mdt,
175                               struct ptlrpc_request *req,
176                               struct mdt_object *src,
177                               struct mdt_object *tgt)
178 {
179         struct md_attr *ma = &info->mti_attr;
180         struct rename_stats *rstats = &mdt->mdt_rename_stats;
181         int rc;
182
183         ma->ma_need = MA_INODE;
184         ma->ma_valid = 0;
185         rc = mo_attr_get(info->mti_env, mdt_object_child(src), ma);
186         if (rc) {
187                 CERROR("%s: "DFID" attr_get, rc = %d\n",
188                        mdt_obd_name(mdt), PFID(mdt_object_fid(src)), rc);
189                 return;
190         }
191
192         if (src == tgt) {
193                 mdt_counter_incr(req, LPROC_MDT_SAMEDIR_RENAME);
194                 lprocfs_oh_tally_log2(&rstats->hist[RENAME_SAMEDIR_SIZE],
195                                       (unsigned int)ma->ma_attr.la_size);
196                 return;
197         }
198
199         mdt_counter_incr(req, LPROC_MDT_CROSSDIR_RENAME);
200         lprocfs_oh_tally_log2(&rstats->hist[RENAME_CROSSDIR_SRC_SIZE],
201                               (unsigned int)ma->ma_attr.la_size);
202
203         ma->ma_need = MA_INODE;
204         ma->ma_valid = 0;
205         rc = mo_attr_get(info->mti_env, mdt_object_child(tgt), ma);
206         if (rc) {
207                 CERROR("%s: "DFID" attr_get, rc = %d\n",
208                        mdt_obd_name(mdt), PFID(mdt_object_fid(tgt)), rc);
209                 return;
210         }
211
212         lprocfs_oh_tally_log2(&rstats->hist[RENAME_CROSSDIR_TGT_SIZE],
213                               (unsigned int)ma->ma_attr.la_size);
214 }
215
216 int mdt_procfs_init(struct mdt_device *mdt, const char *name)
217 {
218         struct obd_device               *obd = mdt2obd_dev(mdt);
219         struct lprocfs_static_vars       lvars;
220         int                              rc;
221         ENTRY;
222
223         LASSERT(name != NULL);
224
225         lprocfs_mdt_init_vars(&lvars);
226         rc = lprocfs_obd_setup(obd, lvars.obd_vars);
227         if (rc) {
228                 CERROR("Can't init lprocfs, rc %d\n", rc);
229                 return rc;
230         }
231         ptlrpc_lprocfs_register_obd(obd);
232
233         obd->obd_proc_exports_entry = proc_mkdir("exports",
234                                                  obd->obd_proc_entry);
235         if (obd->obd_proc_exports_entry)
236                 lprocfs_add_simple(obd->obd_proc_exports_entry,
237                                    "clear", lprocfs_nid_stats_clear_read,
238                                    lprocfs_nid_stats_clear_write, obd, NULL);
239         rc = lprocfs_alloc_md_stats(obd, LPROC_MDT_LAST);
240         if (rc)
241                 return rc;
242         mdt_stats_counter_init(obd->md_stats);
243
244         rc = lprocfs_job_stats_init(obd, LPROC_MDT_LAST,
245                                     mdt_stats_counter_init);
246
247         rc = lproc_mdt_attach_rename_seqstat(mdt);
248         if (rc)
249                 CERROR("%s: MDT can not create rename stats rc = %d\n",
250                        mdt_obd_name(mdt), rc);
251
252         RETURN(rc);
253 }
254
255 void mdt_procfs_fini(struct mdt_device *mdt)
256 {
257         struct obd_device *obd = mdt2obd_dev(mdt);
258
259         if (obd->obd_proc_exports_entry) {
260                 lprocfs_remove_proc_entry("clear", obd->obd_proc_exports_entry);
261                 obd->obd_proc_exports_entry = NULL;
262         }
263         lprocfs_free_per_client_stats(obd);
264         lprocfs_obd_cleanup(obd);
265         ptlrpc_lprocfs_unregister_obd(obd);
266         lprocfs_free_md_stats(obd);
267         lprocfs_free_obd_stats(obd);
268         lprocfs_job_stats_fini(obd);
269 }
270
271 static int lprocfs_rd_identity_expire(char *page, char **start, off_t off,
272                                       int count, int *eof, void *data)
273 {
274         struct obd_device *obd = data;
275         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
276
277         *eof = 1;
278         return snprintf(page, count, "%u\n",
279                         mdt->mdt_identity_cache->uc_entry_expire);
280 }
281
282 static int lprocfs_wr_identity_expire(struct file *file, const char *buffer,
283                                       unsigned long count, void *data)
284 {
285         struct obd_device *obd = data;
286         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
287         int rc, val;
288
289         rc = lprocfs_write_helper(buffer, count, &val);
290         if (rc)
291                 return rc;
292
293         mdt->mdt_identity_cache->uc_entry_expire = val;
294         return count;
295 }
296
297 static int lprocfs_rd_identity_acquire_expire(char *page, char **start,
298                                               off_t off, int count, int *eof,
299                                               void *data)
300 {
301         struct obd_device *obd = data;
302         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
303
304         *eof = 1;
305         return snprintf(page, count, "%u\n",
306                         mdt->mdt_identity_cache->uc_acquire_expire);
307 }
308
309 static int lprocfs_wr_identity_acquire_expire(struct file *file,
310                                               const char *buffer,
311                                               unsigned long count,
312                                               void *data)
313 {
314         struct obd_device *obd = data;
315         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
316         int rc, val;
317
318         rc = lprocfs_write_helper(buffer, count, &val);
319         if (rc)
320                 return rc;
321
322         mdt->mdt_identity_cache->uc_acquire_expire = val;
323         return count;
324 }
325
326 static int lprocfs_rd_identity_upcall(char *page, char **start, off_t off,
327                                       int count, int *eof, void *data)
328 {
329         struct obd_device *obd = data;
330         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
331         struct upcall_cache *hash = mdt->mdt_identity_cache;
332         int len;
333
334         *eof = 1;
335         read_lock(&hash->uc_upcall_rwlock);
336         len = snprintf(page, count, "%s\n", hash->uc_upcall);
337         read_unlock(&hash->uc_upcall_rwlock);
338         return len;
339 }
340
341 static int lprocfs_wr_identity_upcall(struct file *file, const char *buffer,
342                                       unsigned long count, void *data)
343 {
344         struct obd_device       *obd = data;
345         struct mdt_device       *mdt = mdt_dev(obd->obd_lu_dev);
346         struct upcall_cache     *hash = mdt->mdt_identity_cache;
347         int                      rc;
348         char                    *kernbuf;
349
350         if (count >= UC_CACHE_UPCALL_MAXPATH) {
351                 CERROR("%s: identity upcall too long\n", mdt_obd_name(mdt));
352                 return -EINVAL;
353         }
354         OBD_ALLOC(kernbuf, count + 1);
355         if (kernbuf == NULL)
356                 GOTO(failed, rc = -ENOMEM);
357         if (copy_from_user(kernbuf, buffer, count))
358                 GOTO(failed, rc = -EFAULT);
359
360         /* Remove any extraneous bits from the upcall (e.g. linefeeds) */
361         write_lock(&hash->uc_upcall_rwlock);
362         sscanf(kernbuf, "%s", hash->uc_upcall);
363         write_unlock(&hash->uc_upcall_rwlock);
364
365         if (strcmp(hash->uc_name, mdt_obd_name(mdt)) != 0)
366                 CWARN("%s: write to upcall name %s\n",
367                       mdt_obd_name(mdt), hash->uc_upcall);
368
369         if (strcmp(hash->uc_upcall, "NONE") == 0 && mdt->mdt_opts.mo_acl)
370                 CWARN("%s: disable \"identity_upcall\" with ACL enabled maybe "
371                       "cause unexpected \"EACCESS\"\n", mdt_obd_name(mdt));
372
373         CDEBUG(D_CONFIG, "%s: identity upcall set to %s\n", mdt_obd_name(mdt),
374                hash->uc_upcall);
375         OBD_FREE(kernbuf, count + 1);
376         RETURN(count);
377
378  failed:
379         if (kernbuf)
380                 OBD_FREE(kernbuf, count + 1);
381         RETURN(rc);
382 }
383
384 static int lprocfs_wr_identity_flush(struct file *file, const char *buffer,
385                                      unsigned long count, void *data)
386 {
387         struct obd_device *obd = data;
388         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
389         int rc, uid;
390
391         rc = lprocfs_write_helper(buffer, count, &uid);
392         if (rc)
393                 return rc;
394
395         mdt_flush_identity(mdt->mdt_identity_cache, uid);
396         return count;
397 }
398
399 static int lprocfs_wr_identity_info(struct file *file, const char *buffer,
400                                     unsigned long count, void *data)
401 {
402         struct obd_device *obd = data;
403         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
404         struct identity_downcall_data *param;
405         int size = sizeof(*param), rc, checked = 0;
406
407 again:
408         if (count < size) {
409                 CERROR("%s: invalid data count = %lu, size = %d\n",
410                        mdt_obd_name(mdt), count, size);
411                 return -EINVAL;
412         }
413
414         OBD_ALLOC(param, size);
415         if (param == NULL)
416                 return -ENOMEM;
417
418         if (copy_from_user(param, buffer, size)) {
419                 CERROR("%s: bad identity data\n", mdt_obd_name(mdt));
420                 GOTO(out, rc = -EFAULT);
421         }
422
423         if (checked == 0) {
424                 checked = 1;
425                 if (param->idd_magic != IDENTITY_DOWNCALL_MAGIC) {
426                         CERROR("%s: MDS identity downcall bad params\n",
427                                mdt_obd_name(mdt));
428                         GOTO(out, rc = -EINVAL);
429                 }
430
431                 if (param->idd_nperms > N_PERMS_MAX) {
432                         CERROR("%s: perm count %d more than maximum %d\n",
433                                mdt_obd_name(mdt), param->idd_nperms,
434                                N_PERMS_MAX);
435                         GOTO(out, rc = -EINVAL);
436                 }
437
438                 if (param->idd_ngroups > NGROUPS_MAX) {
439                         CERROR("%s: group count %d more than maximum %d\n",
440                                mdt_obd_name(mdt), param->idd_ngroups,
441                                NGROUPS_MAX);
442                         GOTO(out, rc = -EINVAL);
443                 }
444
445                 if (param->idd_ngroups) {
446                         rc = param->idd_ngroups; /* save idd_ngroups */
447                         OBD_FREE(param, size);
448                         size = offsetof(struct identity_downcall_data,
449                                         idd_groups[rc]);
450                         goto again;
451                 }
452         }
453
454         rc = upcall_cache_downcall(mdt->mdt_identity_cache, param->idd_err,
455                                    param->idd_uid, param);
456
457 out:
458         if (param != NULL)
459                 OBD_FREE(param, size);
460
461         return rc ? rc : count;
462 }
463
464 /* for debug only */
465 static int lprocfs_rd_capa(char *page, char **start, off_t off,
466                            int count, int *eof, void *data)
467 {
468         struct obd_device *obd = data;
469         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
470
471         return snprintf(page, count, "capability on: %s %s\n",
472                         mdt->mdt_opts.mo_oss_capa ? "oss" : "",
473                         mdt->mdt_opts.mo_mds_capa ? "mds" : "");
474 }
475
476 static int lprocfs_wr_capa(struct file *file, const char *buffer,
477                            unsigned long count, void *data)
478 {
479         struct obd_device *obd = data;
480         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
481         int val, rc;
482
483         rc = lprocfs_write_helper(buffer, count, &val);
484         if (rc)
485                 return rc;
486
487         if (val < 0 || val > 3) {
488                 CERROR("invalid capability mode, only 0/2/3 is accepted.\n"
489                        " 0:  disable fid capability\n"
490                        " 2:  enable MDS fid capability\n"
491                        " 3:  enable both MDS and OSS fid capability\n");
492                 return -EINVAL;
493         }
494
495         /* OSS fid capability needs enable both MDS and OSS fid capability on
496          * MDS */
497         if (val == 1) {
498                 CERROR("can't enable OSS fid capability only, you should use "
499                        "'3' to enable both MDS and OSS fid capability.\n");
500                 return -EINVAL;
501         }
502
503         mdt->mdt_opts.mo_oss_capa = (val & 0x1);
504         mdt->mdt_opts.mo_mds_capa = !!(val & 0x2);
505         mdt->mdt_capa_conf = 1;
506         LCONSOLE_INFO("MDS %s %s MDS fid capability.\n",
507                       mdt_obd_name(mdt),
508                       mdt->mdt_opts.mo_mds_capa ? "enabled" : "disabled");
509         LCONSOLE_INFO("MDS %s %s OSS fid capability.\n",
510                       mdt_obd_name(mdt),
511                       mdt->mdt_opts.mo_oss_capa ? "enabled" : "disabled");
512         return count;
513 }
514
515 static int lprocfs_rd_capa_count(char *page, char **start, off_t off,
516                                  int count, int *eof, void *data)
517 {
518         return snprintf(page, count, "%d %d\n",
519                         capa_count[CAPA_SITE_CLIENT],
520                         capa_count[CAPA_SITE_SERVER]);
521 }
522
523 static int lprocfs_rd_site_stats(char *page, char **start, off_t off,
524                                  int count, int *eof, void *data)
525 {
526         struct obd_device *obd = data;
527         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
528
529         return lu_site_stats_print(mdt_lu_site(mdt), page, count);
530 }
531
532 static int lprocfs_rd_capa_timeout(char *page, char **start, off_t off,
533                                    int count, int *eof, void *data)
534 {
535         struct obd_device *obd = data;
536         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
537
538         return snprintf(page, count, "%lu\n", mdt->mdt_capa_timeout);
539 }
540
541 static int lprocfs_wr_capa_timeout(struct file *file, const char *buffer,
542                                    unsigned long count, void *data)
543 {
544         struct obd_device *obd = data;
545         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
546         int val, rc;
547
548         rc = lprocfs_write_helper(buffer, count, &val);
549         if (rc)
550                 return rc;
551
552         mdt->mdt_capa_timeout = (unsigned long)val;
553         mdt->mdt_capa_conf = 1;
554         return count;
555 }
556
557 static int lprocfs_rd_ck_timeout(char *page, char **start, off_t off, int count,
558                                  int *eof, void *data)
559 {
560         struct obd_device *obd = data;
561         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
562
563         return snprintf(page, count, "%lu\n", mdt->mdt_ck_timeout);
564 }
565
566 static int lprocfs_wr_ck_timeout(struct file *file, const char *buffer,
567                                  unsigned long count, void *data)
568 {
569         struct obd_device *obd = data;
570         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
571         int val, rc;
572
573         rc = lprocfs_write_helper(buffer, count, &val);
574         if (rc)
575                 return rc;
576
577         mdt->mdt_ck_timeout = (unsigned long)val;
578         mdt->mdt_capa_conf = 1;
579         return count;
580 }
581
582 #define BUFLEN (UUID_MAX + 4)
583
584 static int lprocfs_mdt_wr_evict_client(struct file *file, const char *buffer,
585                                        unsigned long count, void *data)
586 {
587         char *kbuf;
588         char *tmpbuf;
589
590         OBD_ALLOC(kbuf, BUFLEN);
591         if (kbuf == NULL)
592                 return -ENOMEM;
593
594         /*
595          * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1
596          * bytes into kbuf, to ensure that the string is NUL-terminated.
597          * UUID_MAX should include a trailing NUL already.
598          */
599         if (copy_from_user(kbuf, buffer,
600                            min_t(unsigned long, BUFLEN - 1, count))) {
601                 count = -EFAULT;
602                 goto out;
603         }
604         tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count));
605
606         if (strncmp(tmpbuf, "nid:", 4) != 0) {
607                 count = lprocfs_wr_evict_client(file, buffer, count, data);
608                 goto out;
609         }
610
611         CERROR("NOT implement evict client by nid %s\n", tmpbuf);
612
613 out:
614         OBD_FREE(kbuf, BUFLEN);
615         return count;
616 }
617
618 #undef BUFLEN
619
620 static int lprocfs_rd_sec_level(char *page, char **start, off_t off,
621                                 int count, int *eof, void *data)
622 {
623         struct obd_device *obd = data;
624         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
625
626         return snprintf(page, count, "%d\n", mdt->mdt_sec_level);
627 }
628
629 static int lprocfs_wr_sec_level(struct file *file, const char *buffer,
630                                 unsigned long count, void *data)
631 {
632         struct obd_device *obd = data;
633         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
634         int val, rc;
635
636         rc = lprocfs_write_helper(buffer, count, &val);
637         if (rc)
638                 return rc;
639
640         if (val > LUSTRE_SEC_ALL || val < LUSTRE_SEC_NONE)
641                 return -EINVAL;
642
643         if (val == LUSTRE_SEC_SPECIFY) {
644                 CWARN("security level %d will be supported in future.\n",
645                       LUSTRE_SEC_SPECIFY);
646                 return -EINVAL;
647         }
648
649         mdt->mdt_sec_level = val;
650         return count;
651 }
652
653 static int lprocfs_rd_cos(char *page, char **start, off_t off,
654                               int count, int *eof, void *data)
655 {
656         struct obd_device *obd = data;
657         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
658
659         return snprintf(page, count, "%u\n", mdt_cos_is_enabled(mdt));
660 }
661
662 static int lprocfs_wr_cos(struct file *file, const char *buffer,
663                                   unsigned long count, void *data)
664 {
665         struct obd_device *obd = data;
666         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
667         int val, rc;
668
669         rc = lprocfs_write_helper(buffer, count, &val);
670         if (rc)
671                 return rc;
672         mdt_enable_cos(mdt, val);
673         return count;
674 }
675
676 static int lprocfs_rd_root_squash(char *page, char **start, off_t off,
677                                   int count, int *eof, void *data)
678 {
679         struct obd_device *obd = data;
680         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
681
682         return snprintf(page, count, "%u:%u\n", mdt->mdt_squash_uid,
683                         mdt->mdt_squash_gid);
684 }
685
686 static int safe_strtoul(const char *str, char **endp, unsigned long *res)
687 {
688         char n[24];
689
690         *res = simple_strtoul(str, endp, 0);
691         if (str == *endp)
692                 return 1;
693
694         sprintf(n, "%lu", *res);
695         if (strncmp(n, str, *endp - str))
696                 /* overflow */
697                 return 1;
698         return 0;
699 }
700
701 static int lprocfs_wr_root_squash(struct file *file, const char *buffer,
702                                   unsigned long count, void *data)
703 {
704         struct obd_device *obd = data;
705         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
706         int rc;
707         char kernbuf[50], *tmp, *end, *errmsg;
708         unsigned long uid, gid;
709         int nouid, nogid;
710         ENTRY;
711
712         if (count >= sizeof(kernbuf)) {
713                 errmsg = "string too long";
714                 GOTO(failed, rc = -EINVAL);
715         }
716         if (copy_from_user(kernbuf, buffer, count)) {
717                 errmsg = "bad address";
718                 GOTO(failed, rc = -EFAULT);
719         }
720         kernbuf[count] = '\0';
721
722         nouid = nogid = 0;
723         if (safe_strtoul(buffer, &tmp, &uid)) {
724                 uid = mdt->mdt_squash_uid;
725                 nouid = 1;
726         }
727
728         /* skip ':' */
729         if (*tmp == ':') {
730                 tmp++;
731                 if (safe_strtoul(tmp, &end, &gid)) {
732                         gid = mdt->mdt_squash_gid;
733                         nogid = 1;
734                 }
735         } else {
736                 gid = mdt->mdt_squash_gid;
737                 nogid = 1;
738         }
739
740         mdt->mdt_squash_uid = uid;
741         mdt->mdt_squash_gid = gid;
742
743         if (nouid && nogid) {
744                 errmsg = "needs uid:gid format";
745                 GOTO(failed, rc = -EINVAL);
746         }
747
748         LCONSOLE_INFO("%s: root_squash is set to %u:%u\n",
749                       mdt_obd_name(mdt),
750                       mdt->mdt_squash_uid,  mdt->mdt_squash_gid);
751         RETURN(count);
752
753 failed:
754         CWARN("%s: failed to set root_squash to \"%s\", %s: rc %d\n",
755               mdt_obd_name(mdt), buffer, errmsg, rc);
756         RETURN(rc);
757 }
758
759 static int lprocfs_rd_nosquash_nids(char *page, char **start, off_t off,
760                                     int count, int *eof, void *data)
761 {
762         struct obd_device *obd = data;
763         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
764
765         if (mdt->mdt_nosquash_str)
766                 return snprintf(page, count, "%s\n", mdt->mdt_nosquash_str);
767         return snprintf(page, count, "NONE\n");
768 }
769
770 static int lprocfs_wr_nosquash_nids(struct file *file, const char *buffer,
771                                     unsigned long count, void *data)
772 {
773         struct obd_device *obd = data;
774         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
775         int rc;
776         char *kernbuf, *errmsg;
777         cfs_list_t tmp;
778         ENTRY;
779
780         OBD_ALLOC(kernbuf, count + 1);
781         if (kernbuf == NULL) {
782                 errmsg = "no memory";
783                 GOTO(failed, rc = -ENOMEM);
784         }
785         if (copy_from_user(kernbuf, buffer, count)) {
786                 errmsg = "bad address";
787                 GOTO(failed, rc = -EFAULT);
788         }
789         kernbuf[count] = '\0';
790
791         if (!strcmp(kernbuf, "NONE") || !strcmp(kernbuf, "clear")) {
792                 /* empty string is special case */
793                 down_write(&mdt->mdt_squash_sem);
794                 if (!cfs_list_empty(&mdt->mdt_nosquash_nids)) {
795                         cfs_free_nidlist(&mdt->mdt_nosquash_nids);
796                         OBD_FREE(mdt->mdt_nosquash_str,
797                                  mdt->mdt_nosquash_strlen);
798                         mdt->mdt_nosquash_str = NULL;
799                         mdt->mdt_nosquash_strlen = 0;
800                 }
801                 up_write(&mdt->mdt_squash_sem);
802                 LCONSOLE_INFO("%s: nosquash_nids is cleared\n",
803                               mdt_obd_name(mdt));
804                 OBD_FREE(kernbuf, count + 1);
805                 RETURN(count);
806         }
807
808         CFS_INIT_LIST_HEAD(&tmp);
809         if (cfs_parse_nidlist(kernbuf, count, &tmp) <= 0) {
810                 errmsg = "can't parse";
811                 GOTO(failed, rc = -EINVAL);
812         }
813
814         down_write(&mdt->mdt_squash_sem);
815         if (!cfs_list_empty(&mdt->mdt_nosquash_nids)) {
816                 cfs_free_nidlist(&mdt->mdt_nosquash_nids);
817                 OBD_FREE(mdt->mdt_nosquash_str, mdt->mdt_nosquash_strlen);
818         }
819         mdt->mdt_nosquash_str = kernbuf;
820         mdt->mdt_nosquash_strlen = count + 1;
821         cfs_list_splice(&tmp, &mdt->mdt_nosquash_nids);
822
823         LCONSOLE_INFO("%s: nosquash_nids is set to %s\n",
824                       mdt_obd_name(mdt), kernbuf);
825         up_write(&mdt->mdt_squash_sem);
826         RETURN(count);
827
828 failed:
829         CWARN("%s: failed to set nosquash_nids to \"%s\", %s: rc %d\n",
830               mdt_obd_name(mdt), kernbuf, errmsg, rc);
831         if (kernbuf)
832                 OBD_FREE(kernbuf, count + 1);
833         RETURN(rc);
834 }
835
836 static int lprocfs_rd_mdt_som(char *page, char **start, off_t off,
837                               int count, int *eof, void *data)
838 {
839         struct obd_device *obd = data;
840         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
841
842         return snprintf(page, count, "%sabled\n",
843                         mdt->mdt_som_conf ? "en" : "dis");
844 }
845
846 static int lprocfs_wr_mdt_som(struct file *file, const char *buffer,
847                               unsigned long count, void *data)
848 {
849         struct obd_export *exp;
850         struct obd_device *obd = data;
851         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
852         char kernbuf[16];
853         unsigned long val = 0;
854
855         if (count > (sizeof(kernbuf) - 1))
856                 return -EINVAL;
857
858         if (copy_from_user(kernbuf, buffer, count))
859                 return -EFAULT;
860
861         kernbuf[count] = '\0';
862
863         if (!strcmp(kernbuf, "enabled"))
864                 val = 1;
865         else if (strcmp(kernbuf, "disabled"))
866                 return -EINVAL;
867
868         if (mdt->mdt_som_conf == val)
869                 return count;
870
871         if (!obd->obd_process_conf) {
872                 CERROR("Temporary SOM change is not supported, use lctl "
873                        "conf_param for permanent setting\n");
874                 return count;
875         }
876
877         /* 1 stands for self export. */
878         cfs_list_for_each_entry(exp, &obd->obd_exports, exp_obd_chain) {
879                 if (exp == obd->obd_self_export)
880                         continue;
881                 if (exp_connect_flags(exp) & OBD_CONNECT_MDS_MDS)
882                         continue;
883                 /* Some clients are already connected, skip the change */
884                 LCONSOLE_INFO("%s is already connected, SOM will be %s on "
885                               "the next mount\n", exp->exp_client_uuid.uuid,
886                               val ? "enabled" : "disabled");
887                 return count;
888         }
889
890         mdt->mdt_som_conf = val;
891         LCONSOLE_INFO("Enabling SOM\n");
892
893         return count;
894 }
895
896 static int lprocfs_rd_enable_remote_dir(char *page, char **start, off_t off,
897                                         int count, int *eof, void *data)
898 {
899         struct obd_device *obd = data;
900         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
901
902         return snprintf(page, count, "%u\n", mdt->mdt_enable_remote_dir);
903 }
904
905 static int lprocfs_wr_enable_remote_dir(struct file *file, const char *buffer,
906                                         unsigned long count, void *data)
907 {
908         struct obd_device *obd = data;
909         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
910         __u32 val;
911         int rc;
912
913         rc = lprocfs_write_helper(buffer, count, &val);
914         if (rc)
915                 return rc;
916
917         if (val > 1)
918                 return -ERANGE;
919
920         mdt->mdt_enable_remote_dir = val;
921         return count;
922 }
923
924 static int lprocfs_rd_enable_remote_dir_gid(char *page, char **start, off_t off,
925                                             int count, int *eof, void *data)
926 {
927         struct obd_device *obd = data;
928         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
929
930         return snprintf(page, count, "%d\n",
931                         (int)mdt->mdt_enable_remote_dir_gid);
932 }
933
934 static int lprocfs_wr_enable_remote_dir_gid(struct file *file,
935                                             const char *buffer,
936                                             unsigned long count, void *data)
937 {
938         struct obd_device *obd = data;
939         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
940         __u32 val;
941         int rc;
942
943         rc = lprocfs_write_helper(buffer, count, &val);
944         if (rc)
945                 return rc;
946
947         mdt->mdt_enable_remote_dir_gid = val;
948         return count;
949 }
950
951 static struct lprocfs_vars lprocfs_mdt_obd_vars[] = {
952         { "uuid",                       lprocfs_rd_uuid, NULL,
953                                         NULL, NULL, 0 },
954         { "recovery_status",            lprocfs_obd_rd_recovery_status, NULL,
955                                         NULL, NULL, 0 },
956         { "num_exports",                lprocfs_rd_num_exports, NULL,
957                                         NULL, NULL, 0 },
958         { "identity_expire",            lprocfs_rd_identity_expire,
959                                         lprocfs_wr_identity_expire,
960                                         NULL, NULL, 0 },
961         { "identity_acquire_expire",    lprocfs_rd_identity_acquire_expire,
962                                         lprocfs_wr_identity_acquire_expire,
963                                         NULL, NULL, 0 },
964         { "identity_upcall",            lprocfs_rd_identity_upcall,
965                                         lprocfs_wr_identity_upcall,
966                                         NULL, NULL, 0 },
967         { "identity_flush",             NULL, lprocfs_wr_identity_flush,
968                                         NULL, NULL, 0 },
969         { "identity_info",              NULL, lprocfs_wr_identity_info,
970                                         NULL, NULL, 0 },
971         { "capa",                       lprocfs_rd_capa,
972                                         lprocfs_wr_capa,
973                                         NULL, NULL, 0 },
974         { "capa_timeout",               lprocfs_rd_capa_timeout,
975                                         lprocfs_wr_capa_timeout,
976                                         NULL, NULL, 0 },
977         { "capa_key_timeout",           lprocfs_rd_ck_timeout,
978                                         lprocfs_wr_ck_timeout,
979                                         NULL, NULL, 0 },
980         { "capa_count",                 lprocfs_rd_capa_count, NULL,
981                                         NULL, NULL, 0 },
982         { "site_stats",                 lprocfs_rd_site_stats, NULL,
983                                         NULL, NULL, 0 },
984         { "evict_client",               NULL, lprocfs_mdt_wr_evict_client,
985                                         NULL, NULL, 0 },
986         { "hash_stats",                 lprocfs_obd_rd_hash, NULL,
987                                         NULL, NULL, 0 },
988         { "sec_level",                  lprocfs_rd_sec_level,
989                                         lprocfs_wr_sec_level,
990                                         NULL, NULL, 0 },
991         { "commit_on_sharing",          lprocfs_rd_cos, lprocfs_wr_cos,
992                                         NULL, NULL, 0 },
993         { "root_squash",                lprocfs_rd_root_squash,
994                                         lprocfs_wr_root_squash,
995                                         NULL, NULL, 0 },
996         { "nosquash_nids",              lprocfs_rd_nosquash_nids,
997                                         lprocfs_wr_nosquash_nids,
998                                         NULL, NULL, 0 },
999         { "som",                        lprocfs_rd_mdt_som,
1000                                         lprocfs_wr_mdt_som,
1001                                         NULL, NULL, 0 },
1002         { "instance",                   lprocfs_target_rd_instance, NULL,
1003                                         NULL, NULL, 0},
1004         { "ir_factor",                  lprocfs_obd_rd_ir_factor,
1005                                         lprocfs_obd_wr_ir_factor,
1006                                         NULL, NULL, 0 },
1007         { "job_cleanup_interval",       lprocfs_rd_job_interval,
1008                                         lprocfs_wr_job_interval,
1009                                         NULL, NULL, 0 },
1010         { "enable_remote_dir",          lprocfs_rd_enable_remote_dir,
1011                                         lprocfs_wr_enable_remote_dir,
1012                                         NULL, NULL, 0},
1013         { "enable_remote_dir_gid",      lprocfs_rd_enable_remote_dir_gid,
1014                                         lprocfs_wr_enable_remote_dir_gid,
1015                                         NULL, NULL, 0},
1016         { "hsm_control",                lprocfs_rd_hsm_cdt_control,
1017                                         lprocfs_wr_hsm_cdt_control,
1018                                         NULL, NULL, 0 },
1019         { 0 }
1020 };
1021
1022 static struct lprocfs_vars lprocfs_mdt_module_vars[] = {
1023         { "num_refs",                   lprocfs_rd_numrefs, NULL,
1024                                         NULL, NULL, 0 },
1025         { 0 }
1026 };
1027
1028 void lprocfs_mdt_init_vars(struct lprocfs_static_vars *lvars)
1029 {
1030         lvars->module_vars  = lprocfs_mdt_module_vars;
1031         lvars->obd_vars     = lprocfs_mdt_obd_vars;
1032 }
1033
1034 struct lprocfs_vars lprocfs_mds_obd_vars[] = {
1035         { "uuid",       lprocfs_rd_uuid, NULL, NULL, NULL, 0 },
1036         { 0 }
1037 };
1038
1039 struct lprocfs_vars lprocfs_mds_module_vars[] = {
1040         { "num_refs",   lprocfs_rd_numrefs, NULL, NULL, NULL, 0 },
1041         { 0 }
1042 };
1043
1044 void mdt_counter_incr(struct ptlrpc_request *req, int opcode)
1045 {
1046         struct obd_export *exp = req->rq_export;
1047
1048         if (exp->exp_obd && exp->exp_obd->md_stats)
1049                 lprocfs_counter_incr(exp->exp_obd->md_stats, opcode);
1050         if (exp->exp_nid_stats && exp->exp_nid_stats->nid_stats != NULL)
1051                 lprocfs_counter_incr(exp->exp_nid_stats->nid_stats, opcode);
1052         if (exp->exp_obd && exp->exp_obd->u.obt.obt_jobstats.ojs_hash &&
1053             (exp_connect_flags(exp) & OBD_CONNECT_JOBSTATS))
1054                 lprocfs_job_stats_log(exp->exp_obd,
1055                                       lustre_msg_get_jobid(req->rq_reqmsg),
1056                                       opcode, 1);
1057 }
1058
1059 void mdt_stats_counter_init(struct lprocfs_stats *stats)
1060 {
1061         lprocfs_counter_init(stats, LPROC_MDT_OPEN, 0, "open", "reqs");
1062         lprocfs_counter_init(stats, LPROC_MDT_CLOSE, 0, "close", "reqs");
1063         lprocfs_counter_init(stats, LPROC_MDT_MKNOD, 0, "mknod", "reqs");
1064         lprocfs_counter_init(stats, LPROC_MDT_LINK, 0, "link", "reqs");
1065         lprocfs_counter_init(stats, LPROC_MDT_UNLINK, 0, "unlink", "reqs");
1066         lprocfs_counter_init(stats, LPROC_MDT_MKDIR, 0, "mkdir", "reqs");
1067         lprocfs_counter_init(stats, LPROC_MDT_RMDIR, 0, "rmdir", "reqs");
1068         lprocfs_counter_init(stats, LPROC_MDT_RENAME, 0, "rename", "reqs");
1069         lprocfs_counter_init(stats, LPROC_MDT_GETATTR, 0, "getattr", "reqs");
1070         lprocfs_counter_init(stats, LPROC_MDT_SETATTR, 0, "setattr", "reqs");
1071         lprocfs_counter_init(stats, LPROC_MDT_GETXATTR, 0, "getxattr", "reqs");
1072         lprocfs_counter_init(stats, LPROC_MDT_SETXATTR, 0, "setxattr", "reqs");
1073         lprocfs_counter_init(stats, LPROC_MDT_STATFS, 0, "statfs", "reqs");
1074         lprocfs_counter_init(stats, LPROC_MDT_SYNC, 0, "sync", "reqs");
1075         lprocfs_counter_init(stats, LPROC_MDT_SAMEDIR_RENAME, 0,
1076                              "samedir_rename", "reqs");
1077         lprocfs_counter_init(stats, LPROC_MDT_CROSSDIR_RENAME, 0,
1078                              "crossdir_rename", "reqs");
1079 }