aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/configfs/configfs_internal.h3
-rw-r--r--fs/configfs/dir.c90
-rw-r--r--fs/configfs/inode.c38
3 files changed, 131 insertions, 0 deletions
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h
index 762d287123ca..da6061a6df40 100644
--- a/fs/configfs/configfs_internal.h
+++ b/fs/configfs/configfs_internal.h
@@ -39,6 +39,9 @@ struct configfs_dirent {
39 umode_t s_mode; 39 umode_t s_mode;
40 struct dentry * s_dentry; 40 struct dentry * s_dentry;
41 struct iattr * s_iattr; 41 struct iattr * s_iattr;
42#ifdef CONFIG_LOCKDEP
43 int s_depth;
44#endif
42}; 45};
43 46
44#define CONFIGFS_ROOT 0x0001 47#define CONFIGFS_ROOT 0x0001
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 05373db21a4e..d4d871fba21e 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -78,6 +78,92 @@ static const struct dentry_operations configfs_dentry_ops = {
78 .d_delete = configfs_d_delete, 78 .d_delete = configfs_d_delete,
79}; 79};
80 80
81#ifdef CONFIG_LOCKDEP
82
83/*
84 * Helpers to make lockdep happy with our recursive locking of default groups'
85 * inodes (see configfs_attach_group() and configfs_detach_group()).
86 * We put default groups i_mutexes in separate classes according to their depth
87 * from the youngest non-default group ancestor.
88 *
89 * For a non-default group A having default groups A/B, A/C, and A/C/D, default
90 * groups A/B and A/C will have their inode's mutex in class
91 * default_group_class[0], and default group A/C/D will be in
92 * default_group_class[1].
93 *
94 * The lock classes are declared and assigned in inode.c, according to the
95 * s_depth value.
96 * The s_depth value is initialized to -1, adjusted to >= 0 when attaching
97 * default groups, and reset to -1 when all default groups are attached. During
98 * attachment, if configfs_create() sees s_depth > 0, the lock class of the new
99 * inode's mutex is set to default_group_class[s_depth - 1].
100 */
101
102static void configfs_init_dirent_depth(struct configfs_dirent *sd)
103{
104 sd->s_depth = -1;
105}
106
107static void configfs_set_dir_dirent_depth(struct configfs_dirent *parent_sd,
108 struct configfs_dirent *sd)
109{
110 int parent_depth = parent_sd->s_depth;
111
112 if (parent_depth >= 0)
113 sd->s_depth = parent_depth + 1;
114}
115
116static void
117configfs_adjust_dir_dirent_depth_before_populate(struct configfs_dirent *sd)
118{
119 /*
120 * item's i_mutex class is already setup, so s_depth is now only
121 * used to set new sub-directories s_depth, which is always done
122 * with item's i_mutex locked.
123 */
124 /*
125 * sd->s_depth == -1 iff we are a non default group.
126 * else (we are a default group) sd->s_depth > 0 (see
127 * create_dir()).
128 */
129 if (sd->s_depth == -1)
130 /*
131 * We are a non default group and we are going to create
132 * default groups.
133 */
134 sd->s_depth = 0;
135}
136
137static void
138configfs_adjust_dir_dirent_depth_after_populate(struct configfs_dirent *sd)
139{
140 /* We will not create default groups anymore. */
141 sd->s_depth = -1;
142}
143
144#else /* CONFIG_LOCKDEP */
145
146static void configfs_init_dirent_depth(struct configfs_dirent *sd)
147{
148}
149
150static void configfs_set_dir_dirent_depth(struct configfs_dirent *parent_sd,
151 struct configfs_dirent *sd)
152{
153}
154
155static void
156configfs_adjust_dir_dirent_depth_before_populate(struct configfs_dirent *sd)
157{
158}
159
160static void
161configfs_adjust_dir_dirent_depth_after_populate(struct configfs_dirent *sd)
162{
163}
164
165#endif /* CONFIG_LOCKDEP */
166
81/* 167/*
82 * Allocates a new configfs_dirent and links it to the parent configfs_dirent 168 * Allocates a new configfs_dirent and links it to the parent configfs_dirent
83 */ 169 */
@@ -94,6 +180,7 @@ static struct configfs_dirent *configfs_new_dirent(struct configfs_dirent * pare
94 INIT_LIST_HEAD(&sd->s_links); 180 INIT_LIST_HEAD(&sd->s_links);
95 INIT_LIST_HEAD(&sd->s_children); 181 INIT_LIST_HEAD(&sd->s_children);
96 sd->s_element = element; 182 sd->s_element = element;
183 configfs_init_dirent_depth(sd);
97 spin_lock(&configfs_dirent_lock); 184 spin_lock(&configfs_dirent_lock);
98 if (parent_sd->s_type & CONFIGFS_USET_DROPPING) { 185 if (parent_sd->s_type & CONFIGFS_USET_DROPPING) {
99 spin_unlock(&configfs_dirent_lock); 186 spin_unlock(&configfs_dirent_lock);
@@ -187,6 +274,7 @@ static int create_dir(struct config_item * k, struct dentry * p,
187 error = configfs_make_dirent(p->d_fsdata, d, k, mode, 274 error = configfs_make_dirent(p->d_fsdata, d, k, mode,
188 CONFIGFS_DIR | CONFIGFS_USET_CREATING); 275 CONFIGFS_DIR | CONFIGFS_USET_CREATING);
189 if (!error) { 276 if (!error) {
277 configfs_set_dir_dirent_depth(p->d_fsdata, d->d_fsdata);
190 error = configfs_create(d, mode, init_dir); 278 error = configfs_create(d, mode, init_dir);
191 if (!error) { 279 if (!error) {
192 inc_nlink(p->d_inode); 280 inc_nlink(p->d_inode);
@@ -789,11 +877,13 @@ static int configfs_attach_group(struct config_item *parent_item,
789 * error, as rmdir() would. 877 * error, as rmdir() would.
790 */ 878 */
791 mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD); 879 mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
880 configfs_adjust_dir_dirent_depth_before_populate(sd);
792 ret = populate_groups(to_config_group(item)); 881 ret = populate_groups(to_config_group(item));
793 if (ret) { 882 if (ret) {
794 configfs_detach_item(item); 883 configfs_detach_item(item);
795 dentry->d_inode->i_flags |= S_DEAD; 884 dentry->d_inode->i_flags |= S_DEAD;
796 } 885 }
886 configfs_adjust_dir_dirent_depth_after_populate(sd);
797 mutex_unlock(&dentry->d_inode->i_mutex); 887 mutex_unlock(&dentry->d_inode->i_mutex);
798 if (ret) 888 if (ret)
799 d_delete(dentry); 889 d_delete(dentry);
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
index 5d349d38e056..4921e7426d95 100644
--- a/fs/configfs/inode.c
+++ b/fs/configfs/inode.c
@@ -33,10 +33,15 @@
33#include <linux/backing-dev.h> 33#include <linux/backing-dev.h>
34#include <linux/capability.h> 34#include <linux/capability.h>
35#include <linux/sched.h> 35#include <linux/sched.h>
36#include <linux/lockdep.h>
36 37
37#include <linux/configfs.h> 38#include <linux/configfs.h>
38#include "configfs_internal.h" 39#include "configfs_internal.h"
39 40
41#ifdef CONFIG_LOCKDEP
42static struct lock_class_key default_group_class[MAX_LOCK_DEPTH];
43#endif
44
40extern struct super_block * configfs_sb; 45extern struct super_block * configfs_sb;
41 46
42static const struct address_space_operations configfs_aops = { 47static const struct address_space_operations configfs_aops = {
@@ -150,6 +155,38 @@ struct inode * configfs_new_inode(mode_t mode, struct configfs_dirent * sd)
150 return inode; 155 return inode;
151} 156}
152 157
158#ifdef CONFIG_LOCKDEP
159
160static void configfs_set_inode_lock_class(struct configfs_dirent *sd,
161 struct inode *inode)
162{
163 int depth = sd->s_depth;
164
165 if (depth > 0) {
166 if (depth <= ARRAY_SIZE(default_group_class)) {
167 lockdep_set_class(&inode->i_mutex,
168 &default_group_class[depth - 1]);
169 } else {
170 /*
171 * In practice the maximum level of locking depth is
172 * already reached. Just inform about possible reasons.
173 */
174 printk(KERN_INFO "configfs: Too many levels of inodes"
175 " for the locking correctness validator.\n");
176 printk(KERN_INFO "Spurious warnings may appear.\n");
177 }
178 }
179}
180
181#else /* CONFIG_LOCKDEP */
182
183static void configfs_set_inode_lock_class(struct configfs_dirent *sd,
184 struct inode *inode)
185{
186}
187
188#endif /* CONFIG_LOCKDEP */
189
153int configfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *)) 190int configfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
154{ 191{
155 int error = 0; 192 int error = 0;
@@ -162,6 +199,7 @@ int configfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *
162 struct inode *p_inode = dentry->d_parent->d_inode; 199 struct inode *p_inode = dentry->d_parent->d_inode;
163 p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME; 200 p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
164 } 201 }
202 configfs_set_inode_lock_class(sd, inode);
165 goto Proceed; 203 goto Proceed;
166 } 204 }
167 else 205 else