@@ -937,22 +937,39 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info)
937
937
struct btrfs_key found_key ;
938
938
struct btrfs_qgroup * qgroup = NULL ;
939
939
struct btrfs_trans_handle * trans = NULL ;
940
+ struct ulist * ulist = NULL ;
940
941
int ret = 0 ;
941
942
int slot ;
942
943
943
944
mutex_lock (& fs_info -> qgroup_ioctl_lock );
944
945
if (fs_info -> quota_root )
945
946
goto out ;
946
947
947
- fs_info -> qgroup_ulist = ulist_alloc (GFP_KERNEL );
948
- if (!fs_info -> qgroup_ulist ) {
948
+ ulist = ulist_alloc (GFP_KERNEL );
949
+ if (!ulist ) {
949
950
ret = - ENOMEM ;
950
951
goto out ;
951
952
}
952
953
953
954
ret = btrfs_sysfs_add_qgroups (fs_info );
954
955
if (ret < 0 )
955
956
goto out ;
957
+
958
+ /*
959
+ * Unlock qgroup_ioctl_lock before starting the transaction. This is to
960
+ * avoid lock acquisition inversion problems (reported by lockdep) between
961
+ * qgroup_ioctl_lock and the vfs freeze semaphores, acquired when we
962
+ * start a transaction.
963
+ * After we started the transaction lock qgroup_ioctl_lock again and
964
+ * check if someone else created the quota root in the meanwhile. If so,
965
+ * just return success and release the transaction handle.
966
+ *
967
+ * Also we don't need to worry about someone else calling
968
+ * btrfs_sysfs_add_qgroups() after we unlock and getting an error because
969
+ * that function returns 0 (success) when the sysfs entries already exist.
970
+ */
971
+ mutex_unlock (& fs_info -> qgroup_ioctl_lock );
972
+
956
973
/*
957
974
* 1 for quota root item
958
975
* 1 for BTRFS_QGROUP_STATUS item
@@ -962,12 +979,20 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info)
962
979
* would be a lot of overkill.
963
980
*/
964
981
trans = btrfs_start_transaction (tree_root , 2 );
982
+
983
+ mutex_lock (& fs_info -> qgroup_ioctl_lock );
965
984
if (IS_ERR (trans )) {
966
985
ret = PTR_ERR (trans );
967
986
trans = NULL ;
968
987
goto out ;
969
988
}
970
989
990
+ if (fs_info -> quota_root )
991
+ goto out ;
992
+
993
+ fs_info -> qgroup_ulist = ulist ;
994
+ ulist = NULL ;
995
+
971
996
/*
972
997
* initially create the quota tree
973
998
*/
@@ -1125,11 +1150,14 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info)
1125
1150
if (ret ) {
1126
1151
ulist_free (fs_info -> qgroup_ulist );
1127
1152
fs_info -> qgroup_ulist = NULL ;
1128
- if (trans )
1129
- btrfs_end_transaction (trans );
1130
1153
btrfs_sysfs_del_qgroups (fs_info );
1131
1154
}
1132
1155
mutex_unlock (& fs_info -> qgroup_ioctl_lock );
1156
+ if (ret && trans )
1157
+ btrfs_end_transaction (trans );
1158
+ else if (trans )
1159
+ ret = btrfs_end_transaction (trans );
1160
+ ulist_free (ulist );
1133
1161
return ret ;
1134
1162
}
1135
1163
@@ -1142,19 +1170,29 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
1142
1170
mutex_lock (& fs_info -> qgroup_ioctl_lock );
1143
1171
if (!fs_info -> quota_root )
1144
1172
goto out ;
1173
+ mutex_unlock (& fs_info -> qgroup_ioctl_lock );
1145
1174
1146
1175
/*
1147
1176
* 1 For the root item
1148
1177
*
1149
1178
* We should also reserve enough items for the quota tree deletion in
1150
1179
* btrfs_clean_quota_tree but this is not done.
1180
+ *
1181
+ * Also, we must always start a transaction without holding the mutex
1182
+ * qgroup_ioctl_lock, see btrfs_quota_enable().
1151
1183
*/
1152
1184
trans = btrfs_start_transaction (fs_info -> tree_root , 1 );
1185
+
1186
+ mutex_lock (& fs_info -> qgroup_ioctl_lock );
1153
1187
if (IS_ERR (trans )) {
1154
1188
ret = PTR_ERR (trans );
1189
+ trans = NULL ;
1155
1190
goto out ;
1156
1191
}
1157
1192
1193
+ if (!fs_info -> quota_root )
1194
+ goto out ;
1195
+
1158
1196
clear_bit (BTRFS_FS_QUOTA_ENABLED , & fs_info -> flags );
1159
1197
btrfs_qgroup_wait_for_completion (fs_info , false);
1160
1198
spin_lock (& fs_info -> qgroup_lock );
@@ -1168,13 +1206,13 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
1168
1206
ret = btrfs_clean_quota_tree (trans , quota_root );
1169
1207
if (ret ) {
1170
1208
btrfs_abort_transaction (trans , ret );
1171
- goto end_trans ;
1209
+ goto out ;
1172
1210
}
1173
1211
1174
1212
ret = btrfs_del_root (trans , & quota_root -> root_key );
1175
1213
if (ret ) {
1176
1214
btrfs_abort_transaction (trans , ret );
1177
- goto end_trans ;
1215
+ goto out ;
1178
1216
}
1179
1217
1180
1218
list_del (& quota_root -> dirty_list );
@@ -1186,10 +1224,13 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
1186
1224
1187
1225
btrfs_put_root (quota_root );
1188
1226
1189
- end_trans :
1190
- ret = btrfs_end_transaction (trans );
1191
1227
out :
1192
1228
mutex_unlock (& fs_info -> qgroup_ioctl_lock );
1229
+ if (ret && trans )
1230
+ btrfs_end_transaction (trans );
1231
+ else if (trans )
1232
+ ret = btrfs_end_transaction (trans );
1233
+
1193
1234
return ret ;
1194
1235
}
1195
1236
0 commit comments