diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-20 20:20:53 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-20 20:20:53 -0500 |
commit | 71e4634e00119b2fb8dd0da99b3f5ebbb49cc872 (patch) | |
tree | c42a37a98e99aa9ce8a2af79710e295704782a16 /fs/configfs | |
parent | 19a3dd7621af01b7e44a70d16beab59326c38824 (diff) | |
parent | fab683eb12e71ac6057dc42dc7d1e5e71e5cba5e (diff) |
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Pull SCSI target updates from Nicholas Bellinger:
"The highlights this round include:
- Introduce configfs support for unlocked configfs_depend_item()
(krzysztof + andrezej)
- Conversion of usb-gadget target driver to new function registration
interface (andrzej + sebastian)
- Enable qla2xxx FC target mode support for Extended Logins (himansu +
giridhar)
- Enable qla2xxx FC target mode support for Exchange Offload (himansu +
giridhar)
- Add qla2xxx FC target mode irq affinity notification + selective
command queuing. (quinn + himanshu)
- Fix iscsi-target deadlock in se_node_acl configfs deletion (sagi +
nab)
- Convert se_node_acl configfs deletion + se_node_acl->queue_depth to
proper se_session->sess_kref + target_get_session() usage. (hch +
sagi + nab)
- Fix long-standing race between se_node_acl->acl_kref get and
get_initiator_node_acl() lookup. (hch + nab)
- Fix target/user block-size handling, and make sure netlink reaches
all network namespaces (sheng + andy)
Note there is an outstanding bug-fix series for remote I_T nexus port
TMR LUN_RESET has been posted and still being tested, and will likely
become post -rc1 material at this point"
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (56 commits)
scsi: qla2xxxx: avoid type mismatch in comparison
target/user: Make sure netlink would reach all network namespaces
target: Obtain se_node_acl->acl_kref during get_initiator_node_acl
target: Convert ACL change queue_depth se_session reference usage
iscsi-target: Fix potential dead-lock during node acl delete
ib_srpt: Convert acl lookup to modern get_initiator_node_acl usage
tcm_fc: Convert acl lookup to modern get_initiator_node_acl usage
tcm_fc: Wait for command completion before freeing a session
target: Fix a memory leak in target_dev_lba_map_store()
target: Support aborting tasks with a 64-bit tag
usb/gadget: Remove set-but-not-used variables
target: Remove an unused variable
target: Fix indentation in target_core_configfs.c
target/user: Allow user to set block size before enabling device
iser-target: Fix non negative ERR_PTR isert_device_get usage
target/fcoe: Add tag support to tcm_fc
qla2xxx: Check for online flag instead of active reset when transmitting responses
qla2xxx: Set all queues to 4k
qla2xxx: Disable ZIO at start time.
qla2xxx: Move atioq to a different lock to reduce lock contention
...
Diffstat (limited to 'fs/configfs')
-rw-r--r-- | fs/configfs/dir.c | 150 |
1 files changed, 121 insertions, 29 deletions
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 7ae97e83f121..cab612b2ae76 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
@@ -1070,11 +1070,55 @@ out: | |||
1070 | return ret; | 1070 | return ret; |
1071 | } | 1071 | } |
1072 | 1072 | ||
1073 | static int configfs_do_depend_item(struct dentry *subsys_dentry, | ||
1074 | struct config_item *target) | ||
1075 | { | ||
1076 | struct configfs_dirent *p; | ||
1077 | int ret; | ||
1078 | |||
1079 | spin_lock(&configfs_dirent_lock); | ||
1080 | /* Scan the tree, return 0 if found */ | ||
1081 | ret = configfs_depend_prep(subsys_dentry, target); | ||
1082 | if (ret) | ||
1083 | goto out_unlock_dirent_lock; | ||
1084 | |||
1085 | /* | ||
1086 | * We are sure that the item is not about to be removed by rmdir(), and | ||
1087 | * not in the middle of attachment by mkdir(). | ||
1088 | */ | ||
1089 | p = target->ci_dentry->d_fsdata; | ||
1090 | p->s_dependent_count += 1; | ||
1091 | |||
1092 | out_unlock_dirent_lock: | ||
1093 | spin_unlock(&configfs_dirent_lock); | ||
1094 | |||
1095 | return ret; | ||
1096 | } | ||
1097 | |||
1098 | static inline struct configfs_dirent * | ||
1099 | configfs_find_subsys_dentry(struct configfs_dirent *root_sd, | ||
1100 | struct config_item *subsys_item) | ||
1101 | { | ||
1102 | struct configfs_dirent *p; | ||
1103 | struct configfs_dirent *ret = NULL; | ||
1104 | |||
1105 | list_for_each_entry(p, &root_sd->s_children, s_sibling) { | ||
1106 | if (p->s_type & CONFIGFS_DIR && | ||
1107 | p->s_element == subsys_item) { | ||
1108 | ret = p; | ||
1109 | break; | ||
1110 | } | ||
1111 | } | ||
1112 | |||
1113 | return ret; | ||
1114 | } | ||
1115 | |||
1116 | |||
1073 | int configfs_depend_item(struct configfs_subsystem *subsys, | 1117 | int configfs_depend_item(struct configfs_subsystem *subsys, |
1074 | struct config_item *target) | 1118 | struct config_item *target) |
1075 | { | 1119 | { |
1076 | int ret; | 1120 | int ret; |
1077 | struct configfs_dirent *p, *root_sd, *subsys_sd = NULL; | 1121 | struct configfs_dirent *subsys_sd; |
1078 | struct config_item *s_item = &subsys->su_group.cg_item; | 1122 | struct config_item *s_item = &subsys->su_group.cg_item; |
1079 | struct dentry *root; | 1123 | struct dentry *root; |
1080 | 1124 | ||
@@ -1093,39 +1137,15 @@ int configfs_depend_item(struct configfs_subsystem *subsys, | |||
1093 | */ | 1137 | */ |
1094 | mutex_lock(&d_inode(root)->i_mutex); | 1138 | mutex_lock(&d_inode(root)->i_mutex); |
1095 | 1139 | ||
1096 | root_sd = root->d_fsdata; | 1140 | subsys_sd = configfs_find_subsys_dentry(root->d_fsdata, s_item); |
1097 | |||
1098 | list_for_each_entry(p, &root_sd->s_children, s_sibling) { | ||
1099 | if (p->s_type & CONFIGFS_DIR) { | ||
1100 | if (p->s_element == s_item) { | ||
1101 | subsys_sd = p; | ||
1102 | break; | ||
1103 | } | ||
1104 | } | ||
1105 | } | ||
1106 | |||
1107 | if (!subsys_sd) { | 1141 | if (!subsys_sd) { |
1108 | ret = -ENOENT; | 1142 | ret = -ENOENT; |
1109 | goto out_unlock_fs; | 1143 | goto out_unlock_fs; |
1110 | } | 1144 | } |
1111 | 1145 | ||
1112 | /* Ok, now we can trust subsys/s_item */ | 1146 | /* Ok, now we can trust subsys/s_item */ |
1147 | ret = configfs_do_depend_item(subsys_sd->s_dentry, target); | ||
1113 | 1148 | ||
1114 | spin_lock(&configfs_dirent_lock); | ||
1115 | /* Scan the tree, return 0 if found */ | ||
1116 | ret = configfs_depend_prep(subsys_sd->s_dentry, target); | ||
1117 | if (ret) | ||
1118 | goto out_unlock_dirent_lock; | ||
1119 | |||
1120 | /* | ||
1121 | * We are sure that the item is not about to be removed by rmdir(), and | ||
1122 | * not in the middle of attachment by mkdir(). | ||
1123 | */ | ||
1124 | p = target->ci_dentry->d_fsdata; | ||
1125 | p->s_dependent_count += 1; | ||
1126 | |||
1127 | out_unlock_dirent_lock: | ||
1128 | spin_unlock(&configfs_dirent_lock); | ||
1129 | out_unlock_fs: | 1149 | out_unlock_fs: |
1130 | mutex_unlock(&d_inode(root)->i_mutex); | 1150 | mutex_unlock(&d_inode(root)->i_mutex); |
1131 | 1151 | ||
@@ -1144,8 +1164,7 @@ EXPORT_SYMBOL(configfs_depend_item); | |||
1144 | * configfs_depend_item() because we know that that the client driver is | 1164 | * configfs_depend_item() because we know that that the client driver is |
1145 | * pinned, thus the subsystem is pinned, and therefore configfs is pinned. | 1165 | * pinned, thus the subsystem is pinned, and therefore configfs is pinned. |
1146 | */ | 1166 | */ |
1147 | void configfs_undepend_item(struct configfs_subsystem *subsys, | 1167 | void configfs_undepend_item(struct config_item *target) |
1148 | struct config_item *target) | ||
1149 | { | 1168 | { |
1150 | struct configfs_dirent *sd; | 1169 | struct configfs_dirent *sd; |
1151 | 1170 | ||
@@ -1168,6 +1187,79 @@ void configfs_undepend_item(struct configfs_subsystem *subsys, | |||
1168 | } | 1187 | } |
1169 | EXPORT_SYMBOL(configfs_undepend_item); | 1188 | EXPORT_SYMBOL(configfs_undepend_item); |
1170 | 1189 | ||
1190 | /* | ||
1191 | * caller_subsys is a caller's subsystem not target's. This is used to | ||
1192 | * determine if we should lock root and check subsys or not. When we are | ||
1193 | * in the same subsystem as our target there is no need to do locking as | ||
1194 | * we know that subsys is valid and is not unregistered during this function | ||
1195 | * as we are called from callback of one of his children and VFS holds a lock | ||
1196 | * on some inode. Otherwise we have to lock our root to ensure that target's | ||
1197 | * subsystem it is not unregistered during this function. | ||
1198 | */ | ||
1199 | int configfs_depend_item_unlocked(struct configfs_subsystem *caller_subsys, | ||
1200 | struct config_item *target) | ||
1201 | { | ||
1202 | struct configfs_subsystem *target_subsys; | ||
1203 | struct config_group *root, *parent; | ||
1204 | struct configfs_dirent *subsys_sd; | ||
1205 | int ret = -ENOENT; | ||
1206 | |||
1207 | /* Disallow this function for configfs root */ | ||
1208 | if (configfs_is_root(target)) | ||
1209 | return -EINVAL; | ||
1210 | |||
1211 | parent = target->ci_group; | ||
1212 | /* | ||
1213 | * This may happen when someone is trying to depend root | ||
1214 | * directory of some subsystem | ||
1215 | */ | ||
1216 | if (configfs_is_root(&parent->cg_item)) { | ||
1217 | target_subsys = to_configfs_subsystem(to_config_group(target)); | ||
1218 | root = parent; | ||
1219 | } else { | ||
1220 | target_subsys = parent->cg_subsys; | ||
1221 | /* Find a cofnigfs root as we may need it for locking */ | ||
1222 | for (root = parent; !configfs_is_root(&root->cg_item); | ||
1223 | root = root->cg_item.ci_group) | ||
1224 | ; | ||
1225 | } | ||
1226 | |||
1227 | if (target_subsys != caller_subsys) { | ||
1228 | /* | ||
1229 | * We are in other configfs subsystem, so we have to do | ||
1230 | * additional locking to prevent other subsystem from being | ||
1231 | * unregistered | ||
1232 | */ | ||
1233 | mutex_lock(&d_inode(root->cg_item.ci_dentry)->i_mutex); | ||
1234 | |||
1235 | /* | ||
1236 | * As we are trying to depend item from other subsystem | ||
1237 | * we have to check if this subsystem is still registered | ||
1238 | */ | ||
1239 | subsys_sd = configfs_find_subsys_dentry( | ||
1240 | root->cg_item.ci_dentry->d_fsdata, | ||
1241 | &target_subsys->su_group.cg_item); | ||
1242 | if (!subsys_sd) | ||
1243 | goto out_root_unlock; | ||
1244 | } else { | ||
1245 | subsys_sd = target_subsys->su_group.cg_item.ci_dentry->d_fsdata; | ||
1246 | } | ||
1247 | |||
1248 | /* Now we can execute core of depend item */ | ||
1249 | ret = configfs_do_depend_item(subsys_sd->s_dentry, target); | ||
1250 | |||
1251 | if (target_subsys != caller_subsys) | ||
1252 | out_root_unlock: | ||
1253 | /* | ||
1254 | * We were called from subsystem other than our target so we | ||
1255 | * took some locks so now it's time to release them | ||
1256 | */ | ||
1257 | mutex_unlock(&d_inode(root->cg_item.ci_dentry)->i_mutex); | ||
1258 | |||
1259 | return ret; | ||
1260 | } | ||
1261 | EXPORT_SYMBOL(configfs_depend_item_unlocked); | ||
1262 | |||
1171 | static int configfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | 1263 | static int configfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) |
1172 | { | 1264 | { |
1173 | int ret = 0; | 1265 | int ret = 0; |