Merge tag 'rproc-fixes-for-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git...
[platform/adaptation/renesas_rcar/renesas_kernel.git] / fs / exofs / sys.c
1 /*
2  * Copyright (C) 2012
3  * Sachin Bhamare <sbhamare@panasas.com>
4  * Boaz Harrosh <bharrosh@panasas.com>
5  *
6  * This file is part of exofs.
7  *
8  * exofs is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License 2 as published by
10  * the Free Software Foundation.
11  *
12  * exofs is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with exofs; if not, write to the:
19  *      Free Software Foundation <licensing@fsf.org>
20  */
21
22 #include <linux/kobject.h>
23 #include <linux/device.h>
24
25 #include "exofs.h"
26
27 struct odev_attr {
28         struct attribute attr;
29         ssize_t (*show)(struct exofs_dev *, char *);
30         ssize_t (*store)(struct exofs_dev *, const char *, size_t);
31 };
32
33 static ssize_t odev_attr_show(struct kobject *kobj, struct attribute *attr,
34                 char *buf)
35 {
36         struct exofs_dev *edp = container_of(kobj, struct exofs_dev, ed_kobj);
37         struct odev_attr *a = container_of(attr, struct odev_attr, attr);
38
39         return a->show ? a->show(edp, buf) : 0;
40 }
41
42 static ssize_t odev_attr_store(struct kobject *kobj, struct attribute *attr,
43                 const char *buf, size_t len)
44 {
45         struct exofs_dev *edp = container_of(kobj, struct exofs_dev, ed_kobj);
46         struct odev_attr *a = container_of(attr, struct odev_attr, attr);
47
48         return a->store ? a->store(edp, buf, len) : len;
49 }
50
51 static const struct sysfs_ops odev_attr_ops = {
52         .show  = odev_attr_show,
53         .store = odev_attr_store,
54 };
55
56
57 static struct kset *exofs_kset;
58
59 static ssize_t osdname_show(struct exofs_dev *edp, char *buf)
60 {
61         struct osd_dev *odev = edp->ored.od;
62         const struct osd_dev_info *odi = osduld_device_info(odev);
63
64         return snprintf(buf, odi->osdname_len + 1, "%s", odi->osdname);
65 }
66
67 static ssize_t systemid_show(struct exofs_dev *edp, char *buf)
68 {
69         struct osd_dev *odev = edp->ored.od;
70         const struct osd_dev_info *odi = osduld_device_info(odev);
71
72         memcpy(buf, odi->systemid, odi->systemid_len);
73         return odi->systemid_len;
74 }
75
76 static ssize_t uri_show(struct exofs_dev *edp, char *buf)
77 {
78         return snprintf(buf, edp->urilen, "%s", edp->uri);
79 }
80
81 static ssize_t uri_store(struct exofs_dev *edp, const char *buf, size_t len)
82 {
83         edp->urilen = strlen(buf) + 1;
84         edp->uri = krealloc(edp->uri, edp->urilen, GFP_KERNEL);
85         strncpy(edp->uri, buf, edp->urilen);
86         return edp->urilen;
87 }
88
89 #define OSD_ATTR(name, mode, show, store) \
90         static struct odev_attr odev_attr_##name = \
91                                         __ATTR(name, mode, show, store)
92
93 OSD_ATTR(osdname, S_IRUGO, osdname_show, NULL);
94 OSD_ATTR(systemid, S_IRUGO, systemid_show, NULL);
95 OSD_ATTR(uri, S_IRWXU, uri_show, uri_store);
96
97 static struct attribute *odev_attrs[] = {
98         &odev_attr_osdname.attr,
99         &odev_attr_systemid.attr,
100         &odev_attr_uri.attr,
101         NULL,
102 };
103
104 static struct kobj_type odev_ktype = {
105         .default_attrs  = odev_attrs,
106         .sysfs_ops      = &odev_attr_ops,
107 };
108
109 static struct kobj_type uuid_ktype = {
110 };
111
112 void exofs_sysfs_dbg_print(void)
113 {
114 #ifdef CONFIG_EXOFS_DEBUG
115         struct kobject *k_name, *k_tmp;
116
117         list_for_each_entry_safe(k_name, k_tmp, &exofs_kset->list, entry) {
118                 printk(KERN_INFO "%s: name %s ref %d\n",
119                         __func__, kobject_name(k_name),
120                         (int)atomic_read(&k_name->kref.refcount));
121         }
122 #endif
123 }
124 /*
125  * This function removes all kobjects under exofs_kset
126  * At the end of it, exofs_kset kobject will have a refcount
127  * of 1 which gets decremented only on exofs module unload
128  */
129 void exofs_sysfs_sb_del(struct exofs_sb_info *sbi)
130 {
131         struct kobject *k_name, *k_tmp;
132         struct kobject *s_kobj = &sbi->s_kobj;
133
134         list_for_each_entry_safe(k_name, k_tmp, &exofs_kset->list, entry) {
135                 /* Remove all that are children of this SBI */
136                 if (k_name->parent == s_kobj)
137                         kobject_put(k_name);
138         }
139         kobject_put(s_kobj);
140 }
141
142 /*
143  * This function creates sysfs entries to hold the current exofs cluster
144  * instance (uniquely identified by osdname,pid tuple).
145  * This function gets called once per exofs mount instance.
146  */
147 int exofs_sysfs_sb_add(struct exofs_sb_info *sbi,
148                        struct exofs_dt_device_info *dt_dev)
149 {
150         struct kobject *s_kobj;
151         int retval = 0;
152         uint64_t pid = sbi->one_comp.obj.partition;
153
154         /* allocate new uuid dirent */
155         s_kobj = &sbi->s_kobj;
156         s_kobj->kset = exofs_kset;
157         retval = kobject_init_and_add(s_kobj, &uuid_ktype,
158                         &exofs_kset->kobj,  "%s_%llx", dt_dev->osdname, pid);
159         if (retval) {
160                 EXOFS_ERR("ERROR: Failed to create sysfs entry for "
161                           "uuid-%s_%llx => %d\n", dt_dev->osdname, pid, retval);
162                 return -ENOMEM;
163         }
164         return 0;
165 }
166
167 int exofs_sysfs_odev_add(struct exofs_dev *edev, struct exofs_sb_info *sbi)
168 {
169         struct kobject *d_kobj;
170         int retval = 0;
171
172         /* create osd device group which contains following attributes
173          * osdname, systemid & uri
174          */
175         d_kobj = &edev->ed_kobj;
176         d_kobj->kset = exofs_kset;
177         retval = kobject_init_and_add(d_kobj, &odev_ktype,
178                         &sbi->s_kobj, "dev%u", edev->did);
179         if (retval) {
180                 EXOFS_ERR("ERROR: Failed to create sysfs entry for "
181                                 "device dev%u\n", edev->did);
182                 return retval;
183         }
184         return 0;
185 }
186
187 int exofs_sysfs_init(void)
188 {
189         exofs_kset = kset_create_and_add("exofs", NULL, fs_kobj);
190         if (!exofs_kset) {
191                 EXOFS_ERR("ERROR: kset_create_and_add exofs failed\n");
192                 return -ENOMEM;
193         }
194         return 0;
195 }
196
197 void exofs_sysfs_uninit(void)
198 {
199         kset_unregister(exofs_kset);
200 }