diff options
Diffstat (limited to 'fs')
-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 | } | ||