diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /fs/debugfs/inode.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'fs/debugfs/inode.c')
-rw-r--r-- | fs/debugfs/inode.c | 75 |
1 files changed, 39 insertions, 36 deletions
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index d22438ef7674..30a87b3dbcac 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
@@ -27,12 +27,15 @@ | |||
27 | #include <linux/fsnotify.h> | 27 | #include <linux/fsnotify.h> |
28 | #include <linux/string.h> | 28 | #include <linux/string.h> |
29 | #include <linux/magic.h> | 29 | #include <linux/magic.h> |
30 | #include <linux/slab.h> | ||
30 | 31 | ||
31 | static struct vfsmount *debugfs_mount; | 32 | static struct vfsmount *debugfs_mount; |
32 | static int debugfs_mount_count; | 33 | static int debugfs_mount_count; |
33 | static bool debugfs_registered; | 34 | static bool debugfs_registered; |
34 | 35 | ||
35 | static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t dev) | 36 | static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t dev, |
37 | void *data, const struct file_operations *fops) | ||
38 | |||
36 | { | 39 | { |
37 | struct inode *inode = new_inode(sb); | 40 | struct inode *inode = new_inode(sb); |
38 | 41 | ||
@@ -44,14 +47,18 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d | |||
44 | init_special_inode(inode, mode, dev); | 47 | init_special_inode(inode, mode, dev); |
45 | break; | 48 | break; |
46 | case S_IFREG: | 49 | case S_IFREG: |
47 | inode->i_fop = &debugfs_file_operations; | 50 | inode->i_fop = fops ? fops : &debugfs_file_operations; |
51 | inode->i_private = data; | ||
48 | break; | 52 | break; |
49 | case S_IFLNK: | 53 | case S_IFLNK: |
50 | inode->i_op = &debugfs_link_operations; | 54 | inode->i_op = &debugfs_link_operations; |
55 | inode->i_fop = fops; | ||
56 | inode->i_private = data; | ||
51 | break; | 57 | break; |
52 | case S_IFDIR: | 58 | case S_IFDIR: |
53 | inode->i_op = &simple_dir_inode_operations; | 59 | inode->i_op = &simple_dir_inode_operations; |
54 | inode->i_fop = &simple_dir_operations; | 60 | inode->i_fop = fops ? fops : &simple_dir_operations; |
61 | inode->i_private = data; | ||
55 | 62 | ||
56 | /* directory inodes start off with i_nlink == 2 | 63 | /* directory inodes start off with i_nlink == 2 |
57 | * (for "." entry) */ | 64 | * (for "." entry) */ |
@@ -64,7 +71,8 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d | |||
64 | 71 | ||
65 | /* SMP-safe */ | 72 | /* SMP-safe */ |
66 | static int debugfs_mknod(struct inode *dir, struct dentry *dentry, | 73 | static int debugfs_mknod(struct inode *dir, struct dentry *dentry, |
67 | int mode, dev_t dev) | 74 | int mode, dev_t dev, void *data, |
75 | const struct file_operations *fops) | ||
68 | { | 76 | { |
69 | struct inode *inode; | 77 | struct inode *inode; |
70 | int error = -EPERM; | 78 | int error = -EPERM; |
@@ -72,7 +80,7 @@ static int debugfs_mknod(struct inode *dir, struct dentry *dentry, | |||
72 | if (dentry->d_inode) | 80 | if (dentry->d_inode) |
73 | return -EEXIST; | 81 | return -EEXIST; |
74 | 82 | ||
75 | inode = debugfs_get_inode(dir->i_sb, mode, dev); | 83 | inode = debugfs_get_inode(dir->i_sb, mode, dev, data, fops); |
76 | if (inode) { | 84 | if (inode) { |
77 | d_instantiate(dentry, inode); | 85 | d_instantiate(dentry, inode); |
78 | dget(dentry); | 86 | dget(dentry); |
@@ -81,12 +89,13 @@ static int debugfs_mknod(struct inode *dir, struct dentry *dentry, | |||
81 | return error; | 89 | return error; |
82 | } | 90 | } |
83 | 91 | ||
84 | static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | 92 | static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode, |
93 | void *data, const struct file_operations *fops) | ||
85 | { | 94 | { |
86 | int res; | 95 | int res; |
87 | 96 | ||
88 | mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; | 97 | mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; |
89 | res = debugfs_mknod(dir, dentry, mode, 0); | 98 | res = debugfs_mknod(dir, dentry, mode, 0, data, fops); |
90 | if (!res) { | 99 | if (!res) { |
91 | inc_nlink(dir); | 100 | inc_nlink(dir); |
92 | fsnotify_mkdir(dir, dentry); | 101 | fsnotify_mkdir(dir, dentry); |
@@ -94,18 +103,20 @@ static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
94 | return res; | 103 | return res; |
95 | } | 104 | } |
96 | 105 | ||
97 | static int debugfs_link(struct inode *dir, struct dentry *dentry, int mode) | 106 | static int debugfs_link(struct inode *dir, struct dentry *dentry, int mode, |
107 | void *data, const struct file_operations *fops) | ||
98 | { | 108 | { |
99 | mode = (mode & S_IALLUGO) | S_IFLNK; | 109 | mode = (mode & S_IALLUGO) | S_IFLNK; |
100 | return debugfs_mknod(dir, dentry, mode, 0); | 110 | return debugfs_mknod(dir, dentry, mode, 0, data, fops); |
101 | } | 111 | } |
102 | 112 | ||
103 | static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode) | 113 | static int debugfs_create(struct inode *dir, struct dentry *dentry, int mode, |
114 | void *data, const struct file_operations *fops) | ||
104 | { | 115 | { |
105 | int res; | 116 | int res; |
106 | 117 | ||
107 | mode = (mode & S_IALLUGO) | S_IFREG; | 118 | mode = (mode & S_IALLUGO) | S_IFREG; |
108 | res = debugfs_mknod(dir, dentry, mode, 0); | 119 | res = debugfs_mknod(dir, dentry, mode, 0, data, fops); |
109 | if (!res) | 120 | if (!res) |
110 | fsnotify_create(dir, dentry); | 121 | fsnotify_create(dir, dentry); |
111 | return res; | 122 | return res; |
@@ -139,7 +150,9 @@ static struct file_system_type debug_fs_type = { | |||
139 | 150 | ||
140 | static int debugfs_create_by_name(const char *name, mode_t mode, | 151 | static int debugfs_create_by_name(const char *name, mode_t mode, |
141 | struct dentry *parent, | 152 | struct dentry *parent, |
142 | struct dentry **dentry) | 153 | struct dentry **dentry, |
154 | void *data, | ||
155 | const struct file_operations *fops) | ||
143 | { | 156 | { |
144 | int error = 0; | 157 | int error = 0; |
145 | 158 | ||
@@ -148,15 +161,8 @@ static int debugfs_create_by_name(const char *name, mode_t mode, | |||
148 | * block. A pointer to that is in the struct vfsmount that we | 161 | * block. A pointer to that is in the struct vfsmount that we |
149 | * have around. | 162 | * have around. |
150 | */ | 163 | */ |
151 | if (!parent) { | 164 | if (!parent) |
152 | if (debugfs_mount && debugfs_mount->mnt_sb) { | 165 | parent = debugfs_mount->mnt_sb->s_root; |
153 | parent = debugfs_mount->mnt_sb->s_root; | ||
154 | } | ||
155 | } | ||
156 | if (!parent) { | ||
157 | pr_debug("debugfs: Ah! can not find a parent!\n"); | ||
158 | return -EFAULT; | ||
159 | } | ||
160 | 166 | ||
161 | *dentry = NULL; | 167 | *dentry = NULL; |
162 | mutex_lock(&parent->d_inode->i_mutex); | 168 | mutex_lock(&parent->d_inode->i_mutex); |
@@ -164,13 +170,16 @@ static int debugfs_create_by_name(const char *name, mode_t mode, | |||
164 | if (!IS_ERR(*dentry)) { | 170 | if (!IS_ERR(*dentry)) { |
165 | switch (mode & S_IFMT) { | 171 | switch (mode & S_IFMT) { |
166 | case S_IFDIR: | 172 | case S_IFDIR: |
167 | error = debugfs_mkdir(parent->d_inode, *dentry, mode); | 173 | error = debugfs_mkdir(parent->d_inode, *dentry, mode, |
174 | data, fops); | ||
168 | break; | 175 | break; |
169 | case S_IFLNK: | 176 | case S_IFLNK: |
170 | error = debugfs_link(parent->d_inode, *dentry, mode); | 177 | error = debugfs_link(parent->d_inode, *dentry, mode, |
178 | data, fops); | ||
171 | break; | 179 | break; |
172 | default: | 180 | default: |
173 | error = debugfs_create(parent->d_inode, *dentry, mode); | 181 | error = debugfs_create(parent->d_inode, *dentry, mode, |
182 | data, fops); | ||
174 | break; | 183 | break; |
175 | } | 184 | } |
176 | dput(*dentry); | 185 | dput(*dentry); |
@@ -184,7 +193,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode, | |||
184 | /** | 193 | /** |
185 | * debugfs_create_file - create a file in the debugfs filesystem | 194 | * debugfs_create_file - create a file in the debugfs filesystem |
186 | * @name: a pointer to a string containing the name of the file to create. | 195 | * @name: a pointer to a string containing the name of the file to create. |
187 | * @mode: the permission that the file should have | 196 | * @mode: the permission that the file should have. |
188 | * @parent: a pointer to the parent dentry for this file. This should be a | 197 | * @parent: a pointer to the parent dentry for this file. This should be a |
189 | * directory dentry if set. If this paramater is NULL, then the | 198 | * directory dentry if set. If this paramater is NULL, then the |
190 | * file will be created in the root of the debugfs filesystem. | 199 | * file will be created in the root of the debugfs filesystem. |
@@ -195,8 +204,8 @@ static int debugfs_create_by_name(const char *name, mode_t mode, | |||
195 | * this file. | 204 | * this file. |
196 | * | 205 | * |
197 | * This is the basic "create a file" function for debugfs. It allows for a | 206 | * This is the basic "create a file" function for debugfs. It allows for a |
198 | * wide range of flexibility in createing a file, or a directory (if you | 207 | * wide range of flexibility in creating a file, or a directory (if you want |
199 | * want to create a directory, the debugfs_create_dir() function is | 208 | * to create a directory, the debugfs_create_dir() function is |
200 | * recommended to be used instead.) | 209 | * recommended to be used instead.) |
201 | * | 210 | * |
202 | * This function will return a pointer to a dentry if it succeeds. This | 211 | * This function will return a pointer to a dentry if it succeeds. This |
@@ -221,19 +230,13 @@ struct dentry *debugfs_create_file(const char *name, mode_t mode, | |||
221 | if (error) | 230 | if (error) |
222 | goto exit; | 231 | goto exit; |
223 | 232 | ||
224 | error = debugfs_create_by_name(name, mode, parent, &dentry); | 233 | error = debugfs_create_by_name(name, mode, parent, &dentry, |
234 | data, fops); | ||
225 | if (error) { | 235 | if (error) { |
226 | dentry = NULL; | 236 | dentry = NULL; |
227 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); | 237 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); |
228 | goto exit; | 238 | goto exit; |
229 | } | 239 | } |
230 | |||
231 | if (dentry->d_inode) { | ||
232 | if (data) | ||
233 | dentry->d_inode->i_private = data; | ||
234 | if (fops) | ||
235 | dentry->d_inode->i_fop = fops; | ||
236 | } | ||
237 | exit: | 240 | exit: |
238 | return dentry; | 241 | return dentry; |
239 | } | 242 | } |
@@ -494,7 +497,7 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, | |||
494 | } | 497 | } |
495 | d_move(old_dentry, dentry); | 498 | d_move(old_dentry, dentry); |
496 | fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name, | 499 | fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name, |
497 | old_dentry->d_name.name, S_ISDIR(old_dentry->d_inode->i_mode), | 500 | S_ISDIR(old_dentry->d_inode->i_mode), |
498 | NULL, old_dentry); | 501 | NULL, old_dentry); |
499 | fsnotify_oldname_free(old_name); | 502 | fsnotify_oldname_free(old_name); |
500 | unlock_rename(new_dir, old_dir); | 503 | unlock_rename(new_dir, old_dir); |