diff options
| author | Eric W. Biederman <ebiederm@xmission.com> | 2007-07-31 06:15:08 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-10-12 17:51:03 -0400 |
| commit | 90bc61359de0148f8627073d68a22edc7ed9893d (patch) | |
| tree | b054bf0cb9bda41dab498086216f4c0253b2c5ed /fs/sysfs | |
| parent | 869512ab5ab93e5e82ad7d4aaf4ed098d23bfc3f (diff) | |
sysfs: Remove first pass at shadow directory support
While shadow directories appear to be a good idea, the current scheme
of controlling their creation and destruction outside of sysfs appears
to be a locking and maintenance nightmare in the face of sysfs
directories dynamically coming and going. Which can now occur for
directories containing network devices when CONFIG_SYSFS_DEPRECATED is
not set.
This patch removes everything from the initial shadow directory support
that allowed the shadow directory creation to be controlled at a higher
level. So except for a few bits of sysfs_rename_dir everything from
commit b592fcfe7f06c15ec11774b5be7ce0de3aa86e73 is now gone.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'fs/sysfs')
| -rw-r--r-- | fs/sysfs/dir.c | 167 | ||||
| -rw-r--r-- | fs/sysfs/group.c | 1 | ||||
| -rw-r--r-- | fs/sysfs/inode.c | 10 | ||||
| -rw-r--r-- | fs/sysfs/mount.c | 2 | ||||
| -rw-r--r-- | fs/sysfs/sysfs.h | 6 |
5 files changed, 23 insertions, 163 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 86d75e08de60..837073dbadf4 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
| @@ -569,9 +569,6 @@ static void sysfs_drop_dentry(struct sysfs_dirent *sd) | |||
| 569 | spin_unlock(&dcache_lock); | 569 | spin_unlock(&dcache_lock); |
| 570 | spin_unlock(&sysfs_assoc_lock); | 570 | spin_unlock(&sysfs_assoc_lock); |
| 571 | 571 | ||
| 572 | /* dentries for shadowed inodes are pinned, unpin */ | ||
| 573 | if (dentry && sysfs_is_shadowed_inode(dentry->d_inode)) | ||
| 574 | dput(dentry); | ||
| 575 | dput(dentry); | 572 | dput(dentry); |
| 576 | 573 | ||
| 577 | /* adjust nlink and update timestamp */ | 574 | /* adjust nlink and update timestamp */ |
| @@ -723,19 +720,15 @@ int sysfs_create_subdir(struct kobject *kobj, const char *name, | |||
| 723 | /** | 720 | /** |
| 724 | * sysfs_create_dir - create a directory for an object. | 721 | * sysfs_create_dir - create a directory for an object. |
| 725 | * @kobj: object we're creating directory for. | 722 | * @kobj: object we're creating directory for. |
| 726 | * @shadow_parent: parent object. | ||
| 727 | */ | 723 | */ |
| 728 | int sysfs_create_dir(struct kobject *kobj, | 724 | int sysfs_create_dir(struct kobject * kobj) |
| 729 | struct sysfs_dirent *shadow_parent_sd) | ||
| 730 | { | 725 | { |
| 731 | struct sysfs_dirent *parent_sd, *sd; | 726 | struct sysfs_dirent *parent_sd, *sd; |
| 732 | int error = 0; | 727 | int error = 0; |
| 733 | 728 | ||
| 734 | BUG_ON(!kobj); | 729 | BUG_ON(!kobj); |
| 735 | 730 | ||
| 736 | if (shadow_parent_sd) | 731 | if (kobj->parent) |
| 737 | parent_sd = shadow_parent_sd; | ||
| 738 | else if (kobj->parent) | ||
| 739 | parent_sd = kobj->parent->sd; | 732 | parent_sd = kobj->parent->sd; |
| 740 | else if (sysfs_mount && sysfs_mount->mnt_sb) | 733 | else if (sysfs_mount && sysfs_mount->mnt_sb) |
| 741 | parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata; | 734 | parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata; |
| @@ -890,45 +883,44 @@ void sysfs_remove_dir(struct kobject * kobj) | |||
| 890 | __sysfs_remove_dir(sd); | 883 | __sysfs_remove_dir(sd); |
| 891 | } | 884 | } |
| 892 | 885 | ||
| 893 | int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd, | 886 | int sysfs_rename_dir(struct kobject * kobj, const char *new_name) |
| 894 | const char *new_name) | ||
| 895 | { | 887 | { |
| 896 | struct sysfs_dirent *sd = kobj->sd; | 888 | struct sysfs_dirent *sd; |
| 897 | struct dentry *new_parent = NULL; | 889 | struct dentry *parent = NULL; |
| 898 | struct dentry *old_dentry = NULL, *new_dentry = NULL; | 890 | struct dentry *old_dentry = NULL, *new_dentry = NULL; |
| 891 | struct sysfs_dirent *parent_sd; | ||
| 899 | const char *dup_name = NULL; | 892 | const char *dup_name = NULL; |
| 900 | int error; | 893 | int error; |
| 901 | 894 | ||
| 895 | if (!kobj->parent) | ||
| 896 | return -EINVAL; | ||
| 897 | |||
| 902 | /* get dentries */ | 898 | /* get dentries */ |
| 899 | sd = kobj->sd; | ||
| 903 | old_dentry = sysfs_get_dentry(sd); | 900 | old_dentry = sysfs_get_dentry(sd); |
| 904 | if (IS_ERR(old_dentry)) { | 901 | if (IS_ERR(old_dentry)) { |
| 905 | error = PTR_ERR(old_dentry); | 902 | error = PTR_ERR(old_dentry); |
| 906 | goto out_dput; | 903 | goto out_dput; |
| 907 | } | 904 | } |
| 908 | 905 | ||
| 909 | new_parent = sysfs_get_dentry(new_parent_sd); | 906 | parent_sd = kobj->parent->sd; |
| 910 | if (IS_ERR(new_parent)) { | 907 | parent = sysfs_get_dentry(parent_sd); |
| 911 | error = PTR_ERR(new_parent); | 908 | if (IS_ERR(parent)) { |
| 909 | error = PTR_ERR(parent); | ||
| 912 | goto out_dput; | 910 | goto out_dput; |
| 913 | } | 911 | } |
| 914 | 912 | ||
| 915 | /* lock new_parent and get dentry for new name */ | 913 | /* lock parent and get dentry for new name */ |
| 916 | mutex_lock(&new_parent->d_inode->i_mutex); | 914 | mutex_lock(&parent->d_inode->i_mutex); |
| 917 | 915 | ||
| 918 | new_dentry = lookup_one_len(new_name, new_parent, strlen(new_name)); | 916 | new_dentry = lookup_one_len(new_name, parent, strlen(new_name)); |
| 919 | if (IS_ERR(new_dentry)) { | 917 | if (IS_ERR(new_dentry)) { |
| 920 | error = PTR_ERR(new_dentry); | 918 | error = PTR_ERR(new_dentry); |
| 921 | goto out_unlock; | 919 | goto out_unlock; |
| 922 | } | 920 | } |
| 923 | 921 | ||
| 924 | /* By allowing two different directories with the same | ||
| 925 | * d_parent we allow this routine to move between different | ||
| 926 | * shadows of the same directory | ||
| 927 | */ | ||
| 928 | error = -EINVAL; | 922 | error = -EINVAL; |
| 929 | if (old_dentry->d_parent->d_inode != new_parent->d_inode || | 923 | if (old_dentry == new_dentry) |
| 930 | new_dentry->d_parent->d_inode != new_parent->d_inode || | ||
| 931 | old_dentry == new_dentry) | ||
| 932 | goto out_unlock; | 924 | goto out_unlock; |
| 933 | 925 | ||
| 934 | error = -EEXIST; | 926 | error = -EEXIST; |
| @@ -955,9 +947,9 @@ int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd, | |||
| 955 | d_move(sd->s_dentry, new_dentry); | 947 | d_move(sd->s_dentry, new_dentry); |
| 956 | 948 | ||
| 957 | sysfs_unlink_sibling(sd); | 949 | sysfs_unlink_sibling(sd); |
| 958 | sysfs_get(new_parent_sd); | 950 | sysfs_get(parent_sd); |
| 959 | sysfs_put(sd->s_parent); | 951 | sysfs_put(sd->s_parent); |
| 960 | sd->s_parent = new_parent_sd; | 952 | sd->s_parent = parent_sd; |
| 961 | sysfs_link_sibling(sd); | 953 | sysfs_link_sibling(sd); |
| 962 | 954 | ||
| 963 | mutex_unlock(&sysfs_mutex); | 955 | mutex_unlock(&sysfs_mutex); |
| @@ -968,10 +960,10 @@ int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd, | |||
| 968 | out_drop: | 960 | out_drop: |
| 969 | d_drop(new_dentry); | 961 | d_drop(new_dentry); |
| 970 | out_unlock: | 962 | out_unlock: |
| 971 | mutex_unlock(&new_parent->d_inode->i_mutex); | 963 | mutex_unlock(&parent->d_inode->i_mutex); |
| 972 | out_dput: | 964 | out_dput: |
| 973 | kfree(dup_name); | 965 | kfree(dup_name); |
| 974 | dput(new_parent); | 966 | dput(parent); |
| 975 | dput(old_dentry); | 967 | dput(old_dentry); |
| 976 | dput(new_dentry); | 968 | dput(new_dentry); |
| 977 | return error; | 969 | return error; |
| @@ -1192,121 +1184,6 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) | |||
| 1192 | return offset; | 1184 | return offset; |
| 1193 | } | 1185 | } |
| 1194 | 1186 | ||
| 1195 | |||
| 1196 | /** | ||
| 1197 | * sysfs_make_shadowed_dir - Setup so a directory can be shadowed | ||
| 1198 | * @kobj: object we're creating shadow of. | ||
| 1199 | */ | ||
| 1200 | |||
| 1201 | int sysfs_make_shadowed_dir(struct kobject *kobj, | ||
| 1202 | void * (*follow_link)(struct dentry *, struct nameidata *)) | ||
| 1203 | { | ||
| 1204 | struct dentry *dentry; | ||
| 1205 | struct inode *inode; | ||
| 1206 | struct inode_operations *i_op; | ||
| 1207 | |||
| 1208 | /* get dentry for @kobj->sd, dentry of a shadowed dir is pinned */ | ||
| 1209 | dentry = sysfs_get_dentry(kobj->sd); | ||
| 1210 | if (IS_ERR(dentry)) | ||
| 1211 | return PTR_ERR(dentry); | ||
| 1212 | |||
| 1213 | inode = dentry->d_inode; | ||
| 1214 | if (inode->i_op != &sysfs_dir_inode_operations) { | ||
| 1215 | dput(dentry); | ||
| 1216 | return -EINVAL; | ||
| 1217 | } | ||
| 1218 | |||
| 1219 | i_op = kmalloc(sizeof(*i_op), GFP_KERNEL); | ||
| 1220 | if (!i_op) | ||
| 1221 | return -ENOMEM; | ||
| 1222 | |||
| 1223 | memcpy(i_op, &sysfs_dir_inode_operations, sizeof(*i_op)); | ||
| 1224 | i_op->follow_link = follow_link; | ||
| 1225 | |||
| 1226 | /* Locking of inode->i_op? | ||
| 1227 | * Since setting i_op is a single word write and they | ||
| 1228 | * are atomic we should be ok here. | ||
| 1229 | */ | ||
| 1230 | inode->i_op = i_op; | ||
| 1231 | return 0; | ||
| 1232 | } | ||
| 1233 | |||
| 1234 | /** | ||
| 1235 | * sysfs_create_shadow_dir - create a shadow directory for an object. | ||
| 1236 | * @kobj: object we're creating directory for. | ||
| 1237 | * | ||
| 1238 | * sysfs_make_shadowed_dir must already have been called on this | ||
| 1239 | * directory. | ||
| 1240 | */ | ||
| 1241 | |||
| 1242 | struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj) | ||
| 1243 | { | ||
| 1244 | struct sysfs_dirent *parent_sd = kobj->sd->s_parent; | ||
| 1245 | struct dentry *dir, *parent, *shadow; | ||
| 1246 | struct inode *inode; | ||
| 1247 | struct sysfs_dirent *sd; | ||
| 1248 | struct sysfs_addrm_cxt acxt; | ||
| 1249 | |||
| 1250 | dir = sysfs_get_dentry(kobj->sd); | ||
| 1251 | if (IS_ERR(dir)) { | ||
| 1252 | sd = (void *)dir; | ||
| 1253 | goto out; | ||
| 1254 | } | ||
| 1255 | parent = dir->d_parent; | ||
| 1256 | |||
| 1257 | inode = dir->d_inode; | ||
| 1258 | sd = ERR_PTR(-EINVAL); | ||
| 1259 | if (!sysfs_is_shadowed_inode(inode)) | ||
| 1260 | goto out_dput; | ||
| 1261 | |||
| 1262 | shadow = d_alloc(parent, &dir->d_name); | ||
| 1263 | if (!shadow) | ||
| 1264 | goto nomem; | ||
| 1265 | |||
| 1266 | sd = sysfs_new_dirent("_SHADOW_", inode->i_mode, SYSFS_DIR); | ||
| 1267 | if (!sd) | ||
| 1268 | goto nomem; | ||
| 1269 | sd->s_elem.dir.kobj = kobj; | ||
| 1270 | |||
| 1271 | sysfs_addrm_start(&acxt, parent_sd); | ||
| 1272 | |||
| 1273 | /* add but don't link into children list */ | ||
| 1274 | sysfs_add_one(&acxt, sd); | ||
| 1275 | |||
| 1276 | /* attach and instantiate dentry */ | ||
| 1277 | sysfs_attach_dentry(sd, shadow); | ||
| 1278 | d_instantiate(shadow, igrab(inode)); | ||
| 1279 | inc_nlink(inode); /* tj: synchronization? */ | ||
| 1280 | |||
| 1281 | sysfs_addrm_finish(&acxt); | ||
| 1282 | |||
| 1283 | dget(shadow); /* Extra count - pin the dentry in core */ | ||
| 1284 | |||
| 1285 | goto out_dput; | ||
| 1286 | |||
| 1287 | nomem: | ||
| 1288 | dput(shadow); | ||
| 1289 | sd = ERR_PTR(-ENOMEM); | ||
| 1290 | out_dput: | ||
| 1291 | dput(dir); | ||
| 1292 | out: | ||
| 1293 | return sd; | ||
| 1294 | } | ||
| 1295 | |||
| 1296 | /** | ||
| 1297 | * sysfs_remove_shadow_dir - remove an object's directory. | ||
| 1298 | * @shadow_sd: sysfs_dirent of shadow directory | ||
| 1299 | * | ||
| 1300 | * The only thing special about this is that we remove any files in | ||
| 1301 | * the directory before we remove the directory, and we've inlined | ||
| 1302 | * what used to be sysfs_rmdir() below, instead of calling separately. | ||
| 1303 | */ | ||
| 1304 | |||
| 1305 | void sysfs_remove_shadow_dir(struct sysfs_dirent *shadow_sd) | ||
| 1306 | { | ||
| 1307 | __sysfs_remove_dir(shadow_sd); | ||
| 1308 | } | ||
| 1309 | |||
| 1310 | const struct file_operations sysfs_dir_operations = { | 1187 | const struct file_operations sysfs_dir_operations = { |
| 1311 | .open = sysfs_dir_open, | 1188 | .open = sysfs_dir_open, |
| 1312 | .release = sysfs_dir_close, | 1189 | .release = sysfs_dir_close, |
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index e6b904d71633..d1972374655a 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | #include <linux/dcache.h> | 13 | #include <linux/dcache.h> |
| 14 | #include <linux/namei.h> | 14 | #include <linux/namei.h> |
| 15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
| 16 | #include <linux/fs.h> | ||
| 17 | #include "sysfs.h" | 16 | #include "sysfs.h" |
| 18 | 17 | ||
| 19 | 18 | ||
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index aecb6e771e2a..45128b79bc68 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
| @@ -33,16 +33,6 @@ static const struct inode_operations sysfs_inode_operations ={ | |||
| 33 | .setattr = sysfs_setattr, | 33 | .setattr = sysfs_setattr, |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | void sysfs_delete_inode(struct inode *inode) | ||
| 37 | { | ||
| 38 | /* Free the shadowed directory inode operations */ | ||
| 39 | if (sysfs_is_shadowed_inode(inode)) { | ||
| 40 | kfree(inode->i_op); | ||
| 41 | inode->i_op = NULL; | ||
| 42 | } | ||
| 43 | return generic_delete_inode(inode); | ||
| 44 | } | ||
| 45 | |||
| 46 | int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) | 36 | int sysfs_setattr(struct dentry * dentry, struct iattr * iattr) |
| 47 | { | 37 | { |
| 48 | struct inode * inode = dentry->d_inode; | 38 | struct inode * inode = dentry->d_inode; |
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 69a73ae307fe..119f39da1ae1 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c | |||
| @@ -20,7 +20,7 @@ struct kmem_cache *sysfs_dir_cachep; | |||
| 20 | 20 | ||
| 21 | static const struct super_operations sysfs_ops = { | 21 | static const struct super_operations sysfs_ops = { |
| 22 | .statfs = simple_statfs, | 22 | .statfs = simple_statfs, |
| 23 | .drop_inode = sysfs_delete_inode, | 23 | .drop_inode = generic_delete_inode, |
| 24 | }; | 24 | }; |
| 25 | 25 | ||
| 26 | struct sysfs_dirent sysfs_root = { | 26 | struct sysfs_dirent sysfs_root = { |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 6b8c8d76d308..b55e510ea239 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
| @@ -70,7 +70,6 @@ extern void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, | |||
| 70 | struct sysfs_dirent *sd); | 70 | struct sysfs_dirent *sd); |
| 71 | extern int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); | 71 | extern int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); |
| 72 | 72 | ||
| 73 | extern void sysfs_delete_inode(struct inode *inode); | ||
| 74 | extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd); | 73 | extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd); |
| 75 | extern void sysfs_instantiate(struct dentry *dentry, struct inode *inode); | 74 | extern void sysfs_instantiate(struct dentry *dentry, struct inode *inode); |
| 76 | 75 | ||
| @@ -121,8 +120,3 @@ static inline void sysfs_put(struct sysfs_dirent * sd) | |||
| 121 | if (sd && atomic_dec_and_test(&sd->s_count)) | 120 | if (sd && atomic_dec_and_test(&sd->s_count)) |
| 122 | release_sysfs_dirent(sd); | 121 | release_sysfs_dirent(sd); |
| 123 | } | 122 | } |
| 124 | |||
| 125 | static inline int sysfs_is_shadowed_inode(struct inode *inode) | ||
| 126 | { | ||
| 127 | return S_ISDIR(inode->i_mode) && inode->i_op->follow_link; | ||
| 128 | } | ||
