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/dir.c | |
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/dir.c')
-rw-r--r-- | fs/sysfs/dir.c | 167 |
1 files changed, 22 insertions, 145 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, |