aboutsummaryrefslogtreecommitdiffstats
path: root/fs/configfs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-01-20 20:20:53 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-20 20:20:53 -0500
commit71e4634e00119b2fb8dd0da99b3f5ebbb49cc872 (patch)
treec42a37a98e99aa9ce8a2af79710e295704782a16 /fs/configfs
parent19a3dd7621af01b7e44a70d16beab59326c38824 (diff)
parentfab683eb12e71ac6057dc42dc7d1e5e71e5cba5e (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.c150
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
1073static 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
1092out_unlock_dirent_lock:
1093 spin_unlock(&configfs_dirent_lock);
1094
1095 return ret;
1096}
1097
1098static inline struct configfs_dirent *
1099configfs_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
1073int configfs_depend_item(struct configfs_subsystem *subsys, 1117int 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
1127out_unlock_dirent_lock:
1128 spin_unlock(&configfs_dirent_lock);
1129out_unlock_fs: 1149out_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 */
1147void configfs_undepend_item(struct configfs_subsystem *subsys, 1167void 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}
1169EXPORT_SYMBOL(configfs_undepend_item); 1188EXPORT_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 */
1199int 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)
1252out_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}
1261EXPORT_SYMBOL(configfs_depend_item_unlocked);
1262
1171static int configfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) 1263static int configfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
1172{ 1264{
1173 int ret = 0; 1265 int ret = 0;