Whamcloud - gitweb
LU-3181 mdt: mdt_cross_open should allow open by FID on MDT1
[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
148 mdt_rename_stats_seq_write(struct file *file, const char __user *buf,
149                            size_t len, loff_t *off)
150 {
151         struct seq_file *seq = file->private_data;
152         struct mdt_device *mdt = seq->private;
153         int i;
154
155         for (i = 0; i < RENAME_LAST; i++)
156                 lprocfs_oh_clear(&mdt->mdt_rename_stats.hist[i]);
157
158         return len;
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 static int mdt_identity_expire_seq_show(struct seq_file *m, void *data)
217 {
218         struct obd_device *obd = m->private;
219         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
220
221         return seq_printf(m, "%u\n", mdt->mdt_identity_cache->uc_entry_expire);
222 }
223
224 static ssize_t
225 mdt_identity_expire_seq_write(struct file *file, const char __user *buffer,
226                               size_t count, loff_t *off)
227 {
228         struct seq_file   *m = file->private_data;
229         struct obd_device *obd = m->private;
230         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
231         int rc, val;
232
233         rc = lprocfs_write_helper(buffer, count, &val);
234         if (rc)
235                 return rc;
236
237         mdt->mdt_identity_cache->uc_entry_expire = val;
238         return count;
239 }
240 LPROC_SEQ_FOPS(mdt_identity_expire);
241
242 static int mdt_identity_acquire_expire_seq_show(struct seq_file *m, void *data)
243 {
244         struct obd_device *obd = m->private;
245         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
246
247         return seq_printf(m, "%u\n", mdt->mdt_identity_cache->uc_acquire_expire);
248 }
249
250 static ssize_t
251 mdt_identity_acquire_expire_seq_write(struct file *file,
252                                       const char __user *buffer,
253                                       size_t count, loff_t *off)
254 {
255         struct seq_file   *m = file->private_data;
256         struct obd_device *obd = m->private;
257         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
258         int rc, val;
259
260         rc = lprocfs_write_helper(buffer, count, &val);
261         if (rc)
262                 return rc;
263
264         mdt->mdt_identity_cache->uc_acquire_expire = val;
265         return count;
266 }
267 LPROC_SEQ_FOPS(mdt_identity_acquire_expire);
268
269 static int mdt_identity_upcall_seq_show(struct seq_file *m, void *data)
270 {
271         struct obd_device *obd = m->private;
272         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
273         struct upcall_cache *hash = mdt->mdt_identity_cache;
274
275         read_lock(&hash->uc_upcall_rwlock);
276         seq_printf(m, "%s\n", hash->uc_upcall);
277         read_unlock(&hash->uc_upcall_rwlock);
278         return 0;
279 }
280
281 static ssize_t
282 mdt_identity_upcall_seq_write(struct file *file, const char __user *buffer,
283                               size_t count, loff_t *off)
284 {
285         struct seq_file         *m = file->private_data;
286         struct obd_device       *obd = m->private;
287         struct mdt_device       *mdt = mdt_dev(obd->obd_lu_dev);
288         struct upcall_cache     *hash = mdt->mdt_identity_cache;
289         int                      rc;
290         char                    *kernbuf;
291
292         if (count >= UC_CACHE_UPCALL_MAXPATH) {
293                 CERROR("%s: identity upcall too long\n", mdt_obd_name(mdt));
294                 return -EINVAL;
295         }
296         OBD_ALLOC(kernbuf, count + 1);
297         if (kernbuf == NULL)
298                 GOTO(failed, rc = -ENOMEM);
299         if (copy_from_user(kernbuf, buffer, count))
300                 GOTO(failed, rc = -EFAULT);
301
302         /* Remove any extraneous bits from the upcall (e.g. linefeeds) */
303         write_lock(&hash->uc_upcall_rwlock);
304         sscanf(kernbuf, "%s", hash->uc_upcall);
305         write_unlock(&hash->uc_upcall_rwlock);
306
307         if (strcmp(hash->uc_name, mdt_obd_name(mdt)) != 0)
308                 CWARN("%s: write to upcall name %s\n",
309                       mdt_obd_name(mdt), hash->uc_upcall);
310
311         if (strcmp(hash->uc_upcall, "NONE") == 0 && mdt->mdt_opts.mo_acl)
312                 CWARN("%s: disable \"identity_upcall\" with ACL enabled maybe "
313                       "cause unexpected \"EACCESS\"\n", mdt_obd_name(mdt));
314
315         CDEBUG(D_CONFIG, "%s: identity upcall set to %s\n", mdt_obd_name(mdt),
316                hash->uc_upcall);
317         OBD_FREE(kernbuf, count + 1);
318         RETURN(count);
319
320  failed:
321         if (kernbuf)
322                 OBD_FREE(kernbuf, count + 1);
323         RETURN(rc);
324 }
325 LPROC_SEQ_FOPS(mdt_identity_upcall);
326
327 static ssize_t
328 lprocfs_identity_flush_seq_write(struct file *file, const char __user *buffer,
329                                  size_t count, void *data)
330 {
331         struct seq_file   *m = file->private_data;
332         struct obd_device *obd = m->private;
333         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
334         int rc, uid;
335
336         rc = lprocfs_write_helper(buffer, count, &uid);
337         if (rc)
338                 return rc;
339
340         mdt_flush_identity(mdt->mdt_identity_cache, uid);
341         return count;
342 }
343 LPROC_SEQ_FOPS_WO_TYPE(mdt, identity_flush);
344
345 static ssize_t
346 lprocfs_identity_info_seq_write(struct file *file, const char __user *buffer,
347                                 size_t count, void *data)
348 {
349         struct seq_file   *m = file->private_data;
350         struct obd_device *obd = m->private;
351         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
352         struct identity_downcall_data *param;
353         int size = sizeof(*param), rc, checked = 0;
354
355 again:
356         if (count < size) {
357                 CERROR("%s: invalid data count = %lu, size = %d\n",
358                        mdt_obd_name(mdt), (unsigned long) count, size);
359                 return -EINVAL;
360         }
361
362         OBD_ALLOC(param, size);
363         if (param == NULL)
364                 return -ENOMEM;
365
366         if (copy_from_user(param, buffer, size)) {
367                 CERROR("%s: bad identity data\n", mdt_obd_name(mdt));
368                 GOTO(out, rc = -EFAULT);
369         }
370
371         if (checked == 0) {
372                 checked = 1;
373                 if (param->idd_magic != IDENTITY_DOWNCALL_MAGIC) {
374                         CERROR("%s: MDS identity downcall bad params\n",
375                                mdt_obd_name(mdt));
376                         GOTO(out, rc = -EINVAL);
377                 }
378
379                 if (param->idd_nperms > N_PERMS_MAX) {
380                         CERROR("%s: perm count %d more than maximum %d\n",
381                                mdt_obd_name(mdt), param->idd_nperms,
382                                N_PERMS_MAX);
383                         GOTO(out, rc = -EINVAL);
384                 }
385
386                 if (param->idd_ngroups > NGROUPS_MAX) {
387                         CERROR("%s: group count %d more than maximum %d\n",
388                                mdt_obd_name(mdt), param->idd_ngroups,
389                                NGROUPS_MAX);
390                         GOTO(out, rc = -EINVAL);
391                 }
392
393                 if (param->idd_ngroups) {
394                         rc = param->idd_ngroups; /* save idd_ngroups */
395                         OBD_FREE(param, size);
396                         size = offsetof(struct identity_downcall_data,
397                                         idd_groups[rc]);
398                         goto again;
399                 }
400         }
401
402         rc = upcall_cache_downcall(mdt->mdt_identity_cache, param->idd_err,
403                                    param->idd_uid, param);
404
405 out:
406         if (param != NULL)
407                 OBD_FREE(param, size);
408
409         return rc ? rc : count;
410 }
411 LPROC_SEQ_FOPS_WO_TYPE(mdt, identity_info);
412
413 /* for debug only */
414 static int mdt_capa_seq_show(struct seq_file *m, void *data)
415 {
416         struct obd_device *obd = m->private;
417         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
418
419         return seq_printf(m, "capability on: %s %s\n",
420                           mdt->mdt_lut.lut_oss_capa ? "oss" : "",
421                           mdt->mdt_lut.lut_mds_capa ? "mds" : "");
422 }
423
424 static ssize_t
425 mdt_capa_seq_write(struct file *file, const char __user *buffer,
426                    size_t count, loff_t *off)
427 {
428         struct seq_file   *m = file->private_data;
429         struct obd_device *obd = m->private;
430         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
431         int val, rc;
432
433         rc = lprocfs_write_helper(buffer, count, &val);
434         if (rc)
435                 return rc;
436
437         if (val < 0 || val > 3) {
438                 CERROR("invalid capability mode, only 0/2/3 is accepted.\n"
439                        " 0:  disable fid capability\n"
440                        " 2:  enable MDS fid capability\n"
441                        " 3:  enable both MDS and OSS fid capability\n");
442                 return -EINVAL;
443         }
444
445         /* OSS fid capability needs enable both MDS and OSS fid capability on
446          * MDS */
447         if (val == 1) {
448                 CERROR("can't enable OSS fid capability only, you should use "
449                        "'3' to enable both MDS and OSS fid capability.\n");
450                 return -EINVAL;
451         }
452
453         spin_lock(&mdt->mdt_lut.lut_flags_lock);
454         mdt->mdt_lut.lut_oss_capa = !!(val & 0x1);
455         mdt->mdt_lut.lut_mds_capa = !!(val & 0x2);
456         spin_unlock(&mdt->mdt_lut.lut_flags_lock);
457         mdt->mdt_capa_conf = 1;
458         LCONSOLE_INFO("MDS %s %s MDS fid capability.\n",
459                       mdt_obd_name(mdt),
460                       mdt->mdt_lut.lut_mds_capa ? "enabled" : "disabled");
461         LCONSOLE_INFO("MDS %s %s OSS fid capability.\n",
462                       mdt_obd_name(mdt),
463                       mdt->mdt_lut.lut_oss_capa ? "enabled" : "disabled");
464         return count;
465 }
466 LPROC_SEQ_FOPS(mdt_capa);
467
468 static int mdt_capa_count_seq_show(struct seq_file *m, void *data)
469 {
470         return seq_printf(m, "%d %d\n", capa_count[CAPA_SITE_CLIENT],
471                           capa_count[CAPA_SITE_SERVER]);
472 }
473 LPROC_SEQ_FOPS_RO(mdt_capa_count);
474
475 static int mdt_site_stats_seq_show(struct seq_file *m, void *data)
476 {
477         struct obd_device *obd = m->private;
478         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
479
480         return lu_site_stats_seq_print(mdt_lu_site(mdt), m);
481 }
482 LPROC_SEQ_FOPS_RO(mdt_site_stats);
483
484 static int mdt_capa_timeout_seq_show(struct seq_file *m, void *data)
485 {
486         struct obd_device *obd = m->private;
487         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
488
489         return seq_printf(m, "%lu\n", mdt->mdt_capa_timeout);
490 }
491
492 static ssize_t
493 mdt_capa_timeout_seq_write(struct file *file, const char __user *buffer,
494                            size_t count, loff_t *off)
495 {
496         struct seq_file   *m = file->private_data;
497         struct obd_device *obd = m->private;
498         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
499         int val, rc;
500
501         rc = lprocfs_write_helper(buffer, count, &val);
502         if (rc)
503                 return rc;
504
505         mdt->mdt_capa_timeout = (unsigned long)val;
506         mdt->mdt_capa_conf = 1;
507         return count;
508 }
509 LPROC_SEQ_FOPS(mdt_capa_timeout);
510
511 static int mdt_ck_timeout_seq_show(struct seq_file *m, void *data)
512 {
513         struct obd_device *obd = m->private;
514         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
515
516         return seq_printf(m, "%lu\n", mdt->mdt_ck_timeout);
517 }
518
519 static ssize_t
520 mdt_ck_timeout_seq_write(struct file *file, const char __user *buffer,
521                          size_t count, loff_t *off)
522 {
523         struct seq_file   *m = file->private_data;
524         struct obd_device *obd = m->private;
525         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
526         int val, rc;
527
528         rc = lprocfs_write_helper(buffer, count, &val);
529         if (rc)
530                 return rc;
531
532         mdt->mdt_ck_timeout = (unsigned long)val;
533         mdt->mdt_capa_conf = 1;
534         return count;
535 }
536 LPROC_SEQ_FOPS(mdt_ck_timeout);
537
538 #define BUFLEN (UUID_MAX + 4)
539
540 static ssize_t
541 lprocfs_mds_evict_client_seq_write(struct file *file,
542                                    const char __user *buffer,
543                                    size_t count, loff_t *off)
544 {
545         char *kbuf;
546         char *tmpbuf;
547
548         OBD_ALLOC(kbuf, BUFLEN);
549         if (kbuf == NULL)
550                 return -ENOMEM;
551
552         /*
553          * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1
554          * bytes into kbuf, to ensure that the string is NUL-terminated.
555          * UUID_MAX should include a trailing NUL already.
556          */
557         if (copy_from_user(kbuf, buffer,
558                            min_t(unsigned long, BUFLEN - 1, count))) {
559                 count = -EFAULT;
560                 goto out;
561         }
562         tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count));
563
564         if (strncmp(tmpbuf, "nid:", 4) != 0) {
565                 count = lprocfs_evict_client_seq_write(file, buffer, count,
566                                                        off);
567                 goto out;
568         }
569
570         CERROR("NOT implement evict client by nid %s\n", tmpbuf);
571
572 out:
573         OBD_FREE(kbuf, BUFLEN);
574         return count;
575 }
576
577 #undef BUFLEN
578
579 static int mdt_sec_level_seq_show(struct seq_file *m, void *data)
580 {
581         struct obd_device *obd = m->private;
582         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
583
584         return seq_printf(m, "%d\n", mdt->mdt_lut.lut_sec_level);
585 }
586
587 static ssize_t
588 mdt_sec_level_seq_write(struct file *file, const char __user *buffer,
589                         size_t count, loff_t *off)
590 {
591         struct seq_file   *m = file->private_data;
592         struct obd_device *obd = m->private;
593         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
594         int val, rc;
595
596         rc = lprocfs_write_helper(buffer, count, &val);
597         if (rc)
598                 return rc;
599
600         if (val > LUSTRE_SEC_ALL || val < LUSTRE_SEC_NONE)
601                 return -EINVAL;
602
603         if (val == LUSTRE_SEC_SPECIFY) {
604                 CWARN("security level %d will be supported in future.\n",
605                       LUSTRE_SEC_SPECIFY);
606                 return -EINVAL;
607         }
608
609         mdt->mdt_lut.lut_sec_level = val;
610         return count;
611 }
612 LPROC_SEQ_FOPS(mdt_sec_level);
613
614 static int mdt_cos_seq_show(struct seq_file *m, void *data)
615 {
616         struct obd_device *obd = m->private;
617         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
618
619         return seq_printf(m, "%u\n", mdt_cos_is_enabled(mdt));
620 }
621
622 static ssize_t
623 mdt_cos_seq_write(struct file *file, const char __user *buffer,
624                   size_t count, loff_t *off)
625 {
626         struct seq_file   *m = file->private_data;
627         struct obd_device *obd = m->private;
628         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
629         int val, rc;
630
631         rc = lprocfs_write_helper(buffer, count, &val);
632         if (rc)
633                 return rc;
634         mdt_enable_cos(mdt, val);
635         return count;
636 }
637 LPROC_SEQ_FOPS(mdt_cos);
638
639 static int mdt_root_squash_seq_show(struct seq_file *m, void *data)
640 {
641         struct obd_device *obd = m->private;
642         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
643         struct root_squash_info *squash = &mdt->mdt_squash;
644
645         return seq_printf(m, "%u:%u\n", squash->rsi_uid,
646                           squash->rsi_gid);
647 }
648
649 static ssize_t
650 mdt_root_squash_seq_write(struct file *file, const char __user *buffer,
651                           size_t count, loff_t *off)
652 {
653         struct seq_file   *m = file->private_data;
654         struct obd_device *obd = m->private;
655         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
656         struct root_squash_info *squash = &mdt->mdt_squash;
657
658         return lprocfs_wr_root_squash(buffer, count, squash,
659                                       mdt_obd_name(mdt));
660 }
661 LPROC_SEQ_FOPS(mdt_root_squash);
662
663 static int mdt_nosquash_nids_seq_show(struct seq_file *m, void *data)
664 {
665         struct obd_device *obd = m->private;
666         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
667         struct root_squash_info *squash = &mdt->mdt_squash;
668         int len = 0, rc;
669
670         down_read(&squash->rsi_sem);
671         if (!list_empty(&squash->rsi_nosquash_nids)) {
672                 len = cfs_print_nidlist(m->buf + m->count, m->size - m->count,
673                                         &squash->rsi_nosquash_nids);
674                 m->count += len;
675                 rc = seq_printf(m, "\n");
676         } else
677                 rc = seq_printf(m, "NONE\n");
678         up_read(&squash->rsi_sem);
679
680         return rc;
681 }
682
683 static ssize_t
684 mdt_nosquash_nids_seq_write(struct file *file, const char __user *buffer,
685                             size_t count, loff_t *off)
686 {
687         struct seq_file   *m = file->private_data;
688         struct obd_device *obd = m->private;
689         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
690         struct root_squash_info *squash = &mdt->mdt_squash;
691
692         return lprocfs_wr_nosquash_nids(buffer, count, squash,
693                                         mdt_obd_name(mdt));
694 }
695 LPROC_SEQ_FOPS(mdt_nosquash_nids);
696
697 static int mdt_som_seq_show(struct seq_file *m, void *data)
698 {
699         struct obd_device *obd = m->private;
700         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
701
702         return seq_printf(m, "%sabled\n",
703                           mdt->mdt_som_conf ? "en" : "dis");
704 }
705
706 static ssize_t
707 mdt_som_seq_write(struct file *file, const char __user *buffer,
708                   size_t count, loff_t *off)
709 {
710         struct seq_file   *m = file->private_data;
711         struct obd_device *obd = m->private;
712         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
713         struct obd_export *exp;
714         char kernbuf[16];
715         unsigned long val = 0;
716
717         if (count > (sizeof(kernbuf) - 1))
718                 return -EINVAL;
719
720         if (copy_from_user(kernbuf, buffer, count))
721                 return -EFAULT;
722
723         kernbuf[count] = '\0';
724
725         if (!strcmp(kernbuf, "enabled"))
726                 val = 1;
727         else if (strcmp(kernbuf, "disabled"))
728                 return -EINVAL;
729
730         if (mdt->mdt_som_conf == val)
731                 return count;
732
733         if (!obd->obd_process_conf) {
734                 CERROR("Temporary SOM change is not supported, use lctl "
735                        "conf_param for permanent setting\n");
736                 return count;
737         }
738
739         /* 1 stands for self export. */
740         cfs_list_for_each_entry(exp, &obd->obd_exports, exp_obd_chain) {
741                 if (exp == obd->obd_self_export)
742                         continue;
743                 if (exp_connect_flags(exp) & OBD_CONNECT_MDS_MDS)
744                         continue;
745                 /* Some clients are already connected, skip the change */
746                 LCONSOLE_INFO("%s is already connected, SOM will be %s on "
747                               "the next mount\n", exp->exp_client_uuid.uuid,
748                               val ? "enabled" : "disabled");
749                 return count;
750         }
751
752         mdt->mdt_som_conf = val;
753         LCONSOLE_INFO("Enabling SOM\n");
754
755         return count;
756 }
757 LPROC_SEQ_FOPS(mdt_som);
758
759 static int mdt_enable_remote_dir_seq_show(struct seq_file *m, void *data)
760 {
761         struct obd_device *obd = m->private;
762         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
763
764         return seq_printf(m, "%u\n", mdt->mdt_enable_remote_dir);
765 }
766
767 static ssize_t
768 mdt_enable_remote_dir_seq_write(struct file *file, const char __user *buffer,
769                                 size_t count, loff_t *off)
770 {
771         struct seq_file   *m = file->private_data;
772         struct obd_device *obd = m->private;
773         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
774         __u32 val;
775         int rc;
776
777         rc = lprocfs_write_helper(buffer, count, &val);
778         if (rc)
779                 return rc;
780
781         if (val > 1)
782                 return -ERANGE;
783
784         mdt->mdt_enable_remote_dir = val;
785         return count;
786 }
787 LPROC_SEQ_FOPS(mdt_enable_remote_dir);
788
789 static int mdt_enable_remote_dir_gid_seq_show(struct seq_file *m, void *data)
790 {
791         struct obd_device *obd = m->private;
792         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
793
794         return seq_printf(m, "%d\n",
795                           (int)mdt->mdt_enable_remote_dir_gid);
796 }
797
798 static ssize_t
799 mdt_enable_remote_dir_gid_seq_write(struct file *file,
800                                     const char __user *buffer,
801                                     size_t count, loff_t *off)
802 {
803         struct seq_file   *m = file->private_data;
804         struct obd_device *obd = m->private;
805         struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
806         __u32 val;
807         int rc;
808
809         rc = lprocfs_write_helper(buffer, count, &val);
810         if (rc)
811                 return rc;
812
813         mdt->mdt_enable_remote_dir_gid = val;
814         return count;
815 }
816 LPROC_SEQ_FOPS(mdt_enable_remote_dir_gid);
817
818 LPROC_SEQ_FOPS_RO_TYPE(mdt, uuid);
819 LPROC_SEQ_FOPS_RO_TYPE(mdt, recovery_status);
820 LPROC_SEQ_FOPS_RO_TYPE(mdt, num_exports);
821 LPROC_SEQ_FOPS_RO_TYPE(mdt, target_instance);
822 LPROC_SEQ_FOPS_RO_TYPE(mdt, hash);
823 LPROC_SEQ_FOPS_WO_TYPE(mdt, mds_evict_client);
824 LPROC_SEQ_FOPS_RW_TYPE(mdt, job_interval);
825 LPROC_SEQ_FOPS_RW_TYPE(mdt, ir_factor);
826 LPROC_SEQ_FOPS_RW_TYPE(mdt, nid_stats_clear);
827 LPROC_SEQ_FOPS(mdt_hsm_cdt_control);
828
829 static struct lprocfs_seq_vars lprocfs_mdt_obd_vars[] = {
830         { .name =       "uuid",
831           .fops =       &mdt_uuid_fops                          },
832         { .name =       "recovery_status",
833           .fops =       &mdt_recovery_status_fops               },
834         { .name =       "num_exports",
835           .fops =       &mdt_num_exports_fops                   },
836         { .name =       "identity_expire",
837           .fops =       &mdt_identity_expire_fops               },
838         { .name =       "identity_acquire_expire",
839           .fops =       &mdt_identity_acquire_expire_fops       },
840         { .name =       "identity_upcall",
841           .fops =       &mdt_identity_upcall_fops               },
842         { .name =       "identity_flush",
843           .fops =       &mdt_identity_flush_fops                },
844         { .name =       "identity_info",
845           .fops =       &mdt_identity_info_fops                 },
846         { .name =       "capa",
847           .fops =       &mdt_capa_fops                          },
848         { .name =       "capa_timeout",
849           .fops =       &mdt_capa_timeout_fops                  },
850         { .name =       "capa_key_timeout",
851           .fops =       &mdt_ck_timeout_fops                    },
852         { .name =       "capa_count",
853           .fops =       &mdt_capa_count_fops                    },
854         { .name =       "site_stats",
855           .fops =       &mdt_site_stats_fops                    },
856         { .name =       "evict_client",
857           .fops =       &mdt_mds_evict_client_fops              },
858         { .name =       "hash_stats",
859           .fops =       &mdt_hash_fops                          },
860         { .name =       "sec_level",
861           .fops =       &mdt_sec_level_fops                     },
862         { .name =       "commit_on_sharing",
863           .fops =       &mdt_cos_fops                           },
864         { .name =       "root_squash",
865           .fops =       &mdt_root_squash_fops                   },
866         { .name =       "nosquash_nids",
867           .fops =       &mdt_nosquash_nids_fops                 },
868         { .name =       "som",
869           .fops =       &mdt_som_fops                           },
870         { .name =       "instance",
871           .fops =       &mdt_target_instance_fops               },
872         { .name =       "ir_factor",
873           .fops =       &mdt_ir_factor_fops                     },
874         { .name =       "job_cleanup_interval",
875           .fops =       &mdt_job_interval_fops                  },
876         { .name =       "enable_remote_dir",
877           .fops =       &mdt_enable_remote_dir_fops             },
878         { .name =       "enable_remote_dir_gid",
879           .fops =       &mdt_enable_remote_dir_gid_fops         },
880         { .name =       "hsm_control",
881           .fops =       &mdt_hsm_cdt_control_fops               },
882         { 0 }
883 };
884
885 int lprocfs_mdt_print_open_files(cfs_hash_t *hs, cfs_hash_bd_t *bd,
886                                  cfs_hlist_node_t *hnode, void *v)
887 {
888         struct obd_export       *exp = cfs_hash_object(hs, hnode);
889         struct seq_file         *seq = v;
890
891         if (exp->exp_lock_hash != NULL) {
892                 struct mdt_export_data  *med = &exp->exp_mdt_data;
893                 struct mdt_file_data    *mfd;
894
895                 spin_lock(&med->med_open_lock);
896                 cfs_list_for_each_entry(mfd, &med->med_open_head, mfd_list) {
897                         seq_printf(seq, DFID"\n",
898                                    PFID(mdt_object_fid(mfd->mfd_object)));
899                 }
900                 spin_unlock(&med->med_open_lock);
901         }
902
903         return 0;
904 }
905
906 int lprocfs_mdt_open_files_seq_show(struct seq_file *seq, void *v)
907 {
908         struct nid_stat *stats = seq->private;
909         struct obd_device *obd = stats->nid_obd;
910
911         cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
912                               lprocfs_mdt_print_open_files, seq);
913
914         return 0;
915 }
916
917 int lprocfs_mdt_open_files_seq_open(struct inode *inode, struct file *file)
918 {
919         struct seq_file         *seq;
920         int                     rc;
921
922         rc = single_open(file, &lprocfs_mdt_open_files_seq_show, NULL);
923         if (rc != 0)
924                 return rc;
925
926         seq = file->private_data;
927         seq->private = PDE_DATA(inode);
928
929         return 0;
930 }
931
932 void mdt_counter_incr(struct ptlrpc_request *req, int opcode)
933 {
934         struct obd_export *exp = req->rq_export;
935
936         if (exp->exp_obd && exp->exp_obd->obd_md_stats)
937                 lprocfs_counter_incr(exp->exp_obd->obd_md_stats, opcode);
938         if (exp->exp_nid_stats && exp->exp_nid_stats->nid_stats != NULL)
939                 lprocfs_counter_incr(exp->exp_nid_stats->nid_stats, opcode);
940         if (exp->exp_obd && exp->exp_obd->u.obt.obt_jobstats.ojs_hash &&
941             (exp_connect_flags(exp) & OBD_CONNECT_JOBSTATS))
942                 lprocfs_job_stats_log(exp->exp_obd,
943                                       lustre_msg_get_jobid(req->rq_reqmsg),
944                                       opcode, 1);
945 }
946
947 void mdt_stats_counter_init(struct lprocfs_stats *stats)
948 {
949         lprocfs_counter_init(stats, LPROC_MDT_OPEN, 0, "open", "reqs");
950         lprocfs_counter_init(stats, LPROC_MDT_CLOSE, 0, "close", "reqs");
951         lprocfs_counter_init(stats, LPROC_MDT_MKNOD, 0, "mknod", "reqs");
952         lprocfs_counter_init(stats, LPROC_MDT_LINK, 0, "link", "reqs");
953         lprocfs_counter_init(stats, LPROC_MDT_UNLINK, 0, "unlink", "reqs");
954         lprocfs_counter_init(stats, LPROC_MDT_MKDIR, 0, "mkdir", "reqs");
955         lprocfs_counter_init(stats, LPROC_MDT_RMDIR, 0, "rmdir", "reqs");
956         lprocfs_counter_init(stats, LPROC_MDT_RENAME, 0, "rename", "reqs");
957         lprocfs_counter_init(stats, LPROC_MDT_GETATTR, 0, "getattr", "reqs");
958         lprocfs_counter_init(stats, LPROC_MDT_SETATTR, 0, "setattr", "reqs");
959         lprocfs_counter_init(stats, LPROC_MDT_GETXATTR, 0, "getxattr", "reqs");
960         lprocfs_counter_init(stats, LPROC_MDT_SETXATTR, 0, "setxattr", "reqs");
961         lprocfs_counter_init(stats, LPROC_MDT_STATFS, 0, "statfs", "reqs");
962         lprocfs_counter_init(stats, LPROC_MDT_SYNC, 0, "sync", "reqs");
963         lprocfs_counter_init(stats, LPROC_MDT_SAMEDIR_RENAME, 0,
964                              "samedir_rename", "reqs");
965         lprocfs_counter_init(stats, LPROC_MDT_CROSSDIR_RENAME, 0,
966                              "crossdir_rename", "reqs");
967 }
968
969 int mdt_procfs_init(struct mdt_device *mdt, const char *name)
970 {
971         struct obd_device               *obd = mdt2obd_dev(mdt);
972         int                              rc;
973         ENTRY;
974
975         LASSERT(name != NULL);
976
977         obd->obd_vars = lprocfs_mdt_obd_vars;
978         rc = lprocfs_seq_obd_setup(obd);
979         if (rc) {
980                 CERROR("%s: cannot create proc entries: rc = %d\n",
981                        mdt_obd_name(mdt), rc);
982                 return rc;
983         }
984
985         rc = hsm_cdt_procfs_init(mdt);
986         if (rc) {
987                 CERROR("%s: cannot create hsm proc entries: rc = %d\n",
988                        mdt_obd_name(mdt), rc);
989                 return rc;
990         }
991
992         obd->obd_proc_exports_entry = proc_mkdir("exports",
993                                                  obd->obd_proc_entry);
994         if (obd->obd_proc_exports_entry)
995                 lprocfs_add_simple(obd->obd_proc_exports_entry, "clear",
996 #ifndef HAVE_ONLY_PROCFS_SEQ
997                                    NULL, NULL,
998 #endif
999                                    obd, &mdt_nid_stats_clear_fops);
1000         rc = lprocfs_alloc_md_stats(obd, LPROC_MDT_LAST);
1001         if (rc)
1002                 return rc;
1003         mdt_stats_counter_init(obd->obd_md_stats);
1004
1005         rc = lprocfs_job_stats_init(obd, LPROC_MDT_LAST,
1006                                     mdt_stats_counter_init);
1007
1008         rc = lproc_mdt_attach_rename_seqstat(mdt);
1009         if (rc)
1010                 CERROR("%s: MDT can not create rename stats rc = %d\n",
1011                        mdt_obd_name(mdt), rc);
1012
1013         RETURN(rc);
1014 }
1015
1016 void mdt_procfs_fini(struct mdt_device *mdt)
1017 {
1018         struct obd_device *obd = mdt2obd_dev(mdt);
1019
1020         if (obd->obd_proc_exports_entry != NULL) {
1021                 lprocfs_remove_proc_entry("clear", obd->obd_proc_exports_entry);
1022                 obd->obd_proc_exports_entry = NULL;
1023         }
1024
1025         lprocfs_free_per_client_stats(obd);
1026         hsm_cdt_procfs_fini(mdt);
1027         lprocfs_obd_cleanup(obd);
1028         lprocfs_free_md_stats(obd);
1029         lprocfs_free_obd_stats(obd);
1030         lprocfs_job_stats_fini(obd);
1031 }