diff options
Diffstat (limited to 'fs/btrfs/delayed-inode.c')
| -rw-r--r-- | fs/btrfs/delayed-inode.c | 147 |
1 files changed, 100 insertions, 47 deletions
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 34836036f01b..0b278b117cbe 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c | |||
| @@ -875,7 +875,6 @@ static int btrfs_insert_delayed_item(struct btrfs_trans_handle *trans, | |||
| 875 | struct btrfs_delayed_item *delayed_item) | 875 | struct btrfs_delayed_item *delayed_item) |
| 876 | { | 876 | { |
| 877 | struct extent_buffer *leaf; | 877 | struct extent_buffer *leaf; |
| 878 | struct btrfs_item *item; | ||
| 879 | char *ptr; | 878 | char *ptr; |
| 880 | int ret; | 879 | int ret; |
| 881 | 880 | ||
| @@ -886,7 +885,6 @@ static int btrfs_insert_delayed_item(struct btrfs_trans_handle *trans, | |||
| 886 | 885 | ||
| 887 | leaf = path->nodes[0]; | 886 | leaf = path->nodes[0]; |
| 888 | 887 | ||
| 889 | item = btrfs_item_nr(leaf, path->slots[0]); | ||
| 890 | ptr = btrfs_item_ptr(leaf, path->slots[0], char); | 888 | ptr = btrfs_item_ptr(leaf, path->slots[0], char); |
| 891 | 889 | ||
| 892 | write_extent_buffer(leaf, delayed_item->data, (unsigned long)ptr, | 890 | write_extent_buffer(leaf, delayed_item->data, (unsigned long)ptr, |
| @@ -1065,32 +1063,25 @@ static void btrfs_release_delayed_inode(struct btrfs_delayed_node *delayed_node) | |||
| 1065 | } | 1063 | } |
| 1066 | } | 1064 | } |
| 1067 | 1065 | ||
| 1068 | static int btrfs_update_delayed_inode(struct btrfs_trans_handle *trans, | 1066 | static int __btrfs_update_delayed_inode(struct btrfs_trans_handle *trans, |
| 1069 | struct btrfs_root *root, | 1067 | struct btrfs_root *root, |
| 1070 | struct btrfs_path *path, | 1068 | struct btrfs_path *path, |
| 1071 | struct btrfs_delayed_node *node) | 1069 | struct btrfs_delayed_node *node) |
| 1072 | { | 1070 | { |
| 1073 | struct btrfs_key key; | 1071 | struct btrfs_key key; |
| 1074 | struct btrfs_inode_item *inode_item; | 1072 | struct btrfs_inode_item *inode_item; |
| 1075 | struct extent_buffer *leaf; | 1073 | struct extent_buffer *leaf; |
| 1076 | int ret; | 1074 | int ret; |
| 1077 | 1075 | ||
| 1078 | mutex_lock(&node->mutex); | ||
| 1079 | if (!node->inode_dirty) { | ||
| 1080 | mutex_unlock(&node->mutex); | ||
| 1081 | return 0; | ||
| 1082 | } | ||
| 1083 | |||
| 1084 | key.objectid = node->inode_id; | 1076 | key.objectid = node->inode_id; |
| 1085 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); | 1077 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); |
| 1086 | key.offset = 0; | 1078 | key.offset = 0; |
| 1079 | |||
| 1087 | ret = btrfs_lookup_inode(trans, root, path, &key, 1); | 1080 | ret = btrfs_lookup_inode(trans, root, path, &key, 1); |
| 1088 | if (ret > 0) { | 1081 | if (ret > 0) { |
| 1089 | btrfs_release_path(path); | 1082 | btrfs_release_path(path); |
| 1090 | mutex_unlock(&node->mutex); | ||
| 1091 | return -ENOENT; | 1083 | return -ENOENT; |
| 1092 | } else if (ret < 0) { | 1084 | } else if (ret < 0) { |
| 1093 | mutex_unlock(&node->mutex); | ||
| 1094 | return ret; | 1085 | return ret; |
| 1095 | } | 1086 | } |
| 1096 | 1087 | ||
| @@ -1105,11 +1096,47 @@ static int btrfs_update_delayed_inode(struct btrfs_trans_handle *trans, | |||
| 1105 | 1096 | ||
| 1106 | btrfs_delayed_inode_release_metadata(root, node); | 1097 | btrfs_delayed_inode_release_metadata(root, node); |
| 1107 | btrfs_release_delayed_inode(node); | 1098 | btrfs_release_delayed_inode(node); |
| 1108 | mutex_unlock(&node->mutex); | ||
| 1109 | 1099 | ||
| 1110 | return 0; | 1100 | return 0; |
| 1111 | } | 1101 | } |
| 1112 | 1102 | ||
| 1103 | static inline int btrfs_update_delayed_inode(struct btrfs_trans_handle *trans, | ||
| 1104 | struct btrfs_root *root, | ||
| 1105 | struct btrfs_path *path, | ||
| 1106 | struct btrfs_delayed_node *node) | ||
| 1107 | { | ||
| 1108 | int ret; | ||
| 1109 | |||
| 1110 | mutex_lock(&node->mutex); | ||
| 1111 | if (!node->inode_dirty) { | ||
| 1112 | mutex_unlock(&node->mutex); | ||
| 1113 | return 0; | ||
| 1114 | } | ||
| 1115 | |||
| 1116 | ret = __btrfs_update_delayed_inode(trans, root, path, node); | ||
| 1117 | mutex_unlock(&node->mutex); | ||
| 1118 | return ret; | ||
| 1119 | } | ||
| 1120 | |||
| 1121 | static inline int | ||
| 1122 | __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans, | ||
| 1123 | struct btrfs_path *path, | ||
| 1124 | struct btrfs_delayed_node *node) | ||
| 1125 | { | ||
| 1126 | int ret; | ||
| 1127 | |||
| 1128 | ret = btrfs_insert_delayed_items(trans, path, node->root, node); | ||
| 1129 | if (ret) | ||
| 1130 | return ret; | ||
| 1131 | |||
| 1132 | ret = btrfs_delete_delayed_items(trans, path, node->root, node); | ||
| 1133 | if (ret) | ||
| 1134 | return ret; | ||
| 1135 | |||
| 1136 | ret = btrfs_update_delayed_inode(trans, node->root, path, node); | ||
| 1137 | return ret; | ||
| 1138 | } | ||
| 1139 | |||
| 1113 | /* | 1140 | /* |
| 1114 | * Called when committing the transaction. | 1141 | * Called when committing the transaction. |
| 1115 | * Returns 0 on success. | 1142 | * Returns 0 on success. |
| @@ -1119,7 +1146,6 @@ static int btrfs_update_delayed_inode(struct btrfs_trans_handle *trans, | |||
| 1119 | static int __btrfs_run_delayed_items(struct btrfs_trans_handle *trans, | 1146 | static int __btrfs_run_delayed_items(struct btrfs_trans_handle *trans, |
| 1120 | struct btrfs_root *root, int nr) | 1147 | struct btrfs_root *root, int nr) |
| 1121 | { | 1148 | { |
| 1122 | struct btrfs_root *curr_root = root; | ||
| 1123 | struct btrfs_delayed_root *delayed_root; | 1149 | struct btrfs_delayed_root *delayed_root; |
| 1124 | struct btrfs_delayed_node *curr_node, *prev_node; | 1150 | struct btrfs_delayed_node *curr_node, *prev_node; |
| 1125 | struct btrfs_path *path; | 1151 | struct btrfs_path *path; |
| @@ -1142,15 +1168,8 @@ static int __btrfs_run_delayed_items(struct btrfs_trans_handle *trans, | |||
| 1142 | 1168 | ||
| 1143 | curr_node = btrfs_first_delayed_node(delayed_root); | 1169 | curr_node = btrfs_first_delayed_node(delayed_root); |
| 1144 | while (curr_node && (!count || (count && nr--))) { | 1170 | while (curr_node && (!count || (count && nr--))) { |
| 1145 | curr_root = curr_node->root; | 1171 | ret = __btrfs_commit_inode_delayed_items(trans, path, |
| 1146 | ret = btrfs_insert_delayed_items(trans, path, curr_root, | 1172 | curr_node); |
| 1147 | curr_node); | ||
| 1148 | if (!ret) | ||
| 1149 | ret = btrfs_delete_delayed_items(trans, path, | ||
| 1150 | curr_root, curr_node); | ||
| 1151 | if (!ret) | ||
| 1152 | ret = btrfs_update_delayed_inode(trans, curr_root, | ||
| 1153 | path, curr_node); | ||
| 1154 | if (ret) { | 1173 | if (ret) { |
| 1155 | btrfs_release_delayed_node(curr_node); | 1174 | btrfs_release_delayed_node(curr_node); |
| 1156 | curr_node = NULL; | 1175 | curr_node = NULL; |
| @@ -1183,51 +1202,93 @@ int btrfs_run_delayed_items_nr(struct btrfs_trans_handle *trans, | |||
| 1183 | return __btrfs_run_delayed_items(trans, root, nr); | 1202 | return __btrfs_run_delayed_items(trans, root, nr); |
| 1184 | } | 1203 | } |
| 1185 | 1204 | ||
| 1186 | static int __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans, | 1205 | int btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans, |
| 1187 | struct btrfs_delayed_node *node) | 1206 | struct inode *inode) |
| 1188 | { | 1207 | { |
| 1208 | struct btrfs_delayed_node *delayed_node = btrfs_get_delayed_node(inode); | ||
| 1189 | struct btrfs_path *path; | 1209 | struct btrfs_path *path; |
| 1190 | struct btrfs_block_rsv *block_rsv; | 1210 | struct btrfs_block_rsv *block_rsv; |
| 1191 | int ret; | 1211 | int ret; |
| 1192 | 1212 | ||
| 1213 | if (!delayed_node) | ||
| 1214 | return 0; | ||
| 1215 | |||
| 1216 | mutex_lock(&delayed_node->mutex); | ||
| 1217 | if (!delayed_node->count) { | ||
| 1218 | mutex_unlock(&delayed_node->mutex); | ||
| 1219 | btrfs_release_delayed_node(delayed_node); | ||
| 1220 | return 0; | ||
| 1221 | } | ||
| 1222 | mutex_unlock(&delayed_node->mutex); | ||
| 1223 | |||
| 1193 | path = btrfs_alloc_path(); | 1224 | path = btrfs_alloc_path(); |
| 1194 | if (!path) | 1225 | if (!path) |
| 1195 | return -ENOMEM; | 1226 | return -ENOMEM; |
| 1196 | path->leave_spinning = 1; | 1227 | path->leave_spinning = 1; |
| 1197 | 1228 | ||
| 1198 | block_rsv = trans->block_rsv; | 1229 | block_rsv = trans->block_rsv; |
| 1199 | trans->block_rsv = &node->root->fs_info->delayed_block_rsv; | 1230 | trans->block_rsv = &delayed_node->root->fs_info->delayed_block_rsv; |
| 1200 | 1231 | ||
| 1201 | ret = btrfs_insert_delayed_items(trans, path, node->root, node); | 1232 | ret = __btrfs_commit_inode_delayed_items(trans, path, delayed_node); |
| 1202 | if (!ret) | ||
| 1203 | ret = btrfs_delete_delayed_items(trans, path, node->root, node); | ||
| 1204 | if (!ret) | ||
| 1205 | ret = btrfs_update_delayed_inode(trans, node->root, path, node); | ||
| 1206 | btrfs_free_path(path); | ||
| 1207 | 1233 | ||
| 1234 | btrfs_release_delayed_node(delayed_node); | ||
| 1235 | btrfs_free_path(path); | ||
| 1208 | trans->block_rsv = block_rsv; | 1236 | trans->block_rsv = block_rsv; |
| 1237 | |||
| 1209 | return ret; | 1238 | return ret; |
| 1210 | } | 1239 | } |
| 1211 | 1240 | ||
| 1212 | int btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans, | 1241 | int btrfs_commit_inode_delayed_inode(struct inode *inode) |
| 1213 | struct inode *inode) | ||
| 1214 | { | 1242 | { |
| 1243 | struct btrfs_trans_handle *trans; | ||
| 1215 | struct btrfs_delayed_node *delayed_node = btrfs_get_delayed_node(inode); | 1244 | struct btrfs_delayed_node *delayed_node = btrfs_get_delayed_node(inode); |
| 1245 | struct btrfs_path *path; | ||
| 1246 | struct btrfs_block_rsv *block_rsv; | ||
| 1216 | int ret; | 1247 | int ret; |
| 1217 | 1248 | ||
| 1218 | if (!delayed_node) | 1249 | if (!delayed_node) |
| 1219 | return 0; | 1250 | return 0; |
| 1220 | 1251 | ||
| 1221 | mutex_lock(&delayed_node->mutex); | 1252 | mutex_lock(&delayed_node->mutex); |
| 1222 | if (!delayed_node->count) { | 1253 | if (!delayed_node->inode_dirty) { |
| 1223 | mutex_unlock(&delayed_node->mutex); | 1254 | mutex_unlock(&delayed_node->mutex); |
| 1224 | btrfs_release_delayed_node(delayed_node); | 1255 | btrfs_release_delayed_node(delayed_node); |
| 1225 | return 0; | 1256 | return 0; |
| 1226 | } | 1257 | } |
| 1227 | mutex_unlock(&delayed_node->mutex); | 1258 | mutex_unlock(&delayed_node->mutex); |
| 1228 | 1259 | ||
| 1229 | ret = __btrfs_commit_inode_delayed_items(trans, delayed_node); | 1260 | trans = btrfs_join_transaction(delayed_node->root); |
| 1261 | if (IS_ERR(trans)) { | ||
| 1262 | ret = PTR_ERR(trans); | ||
| 1263 | goto out; | ||
| 1264 | } | ||
| 1265 | |||
| 1266 | path = btrfs_alloc_path(); | ||
| 1267 | if (!path) { | ||
| 1268 | ret = -ENOMEM; | ||
| 1269 | goto trans_out; | ||
| 1270 | } | ||
| 1271 | path->leave_spinning = 1; | ||
| 1272 | |||
| 1273 | block_rsv = trans->block_rsv; | ||
| 1274 | trans->block_rsv = &delayed_node->root->fs_info->delayed_block_rsv; | ||
| 1275 | |||
| 1276 | mutex_lock(&delayed_node->mutex); | ||
| 1277 | if (delayed_node->inode_dirty) | ||
| 1278 | ret = __btrfs_update_delayed_inode(trans, delayed_node->root, | ||
| 1279 | path, delayed_node); | ||
| 1280 | else | ||
| 1281 | ret = 0; | ||
| 1282 | mutex_unlock(&delayed_node->mutex); | ||
| 1283 | |||
| 1284 | btrfs_free_path(path); | ||
| 1285 | trans->block_rsv = block_rsv; | ||
| 1286 | trans_out: | ||
| 1287 | btrfs_end_transaction(trans, delayed_node->root); | ||
| 1288 | btrfs_btree_balance_dirty(delayed_node->root); | ||
| 1289 | out: | ||
| 1230 | btrfs_release_delayed_node(delayed_node); | 1290 | btrfs_release_delayed_node(delayed_node); |
| 1291 | |||
| 1231 | return ret; | 1292 | return ret; |
| 1232 | } | 1293 | } |
| 1233 | 1294 | ||
| @@ -1258,7 +1319,6 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work) | |||
| 1258 | struct btrfs_root *root; | 1319 | struct btrfs_root *root; |
| 1259 | struct btrfs_block_rsv *block_rsv; | 1320 | struct btrfs_block_rsv *block_rsv; |
| 1260 | int need_requeue = 0; | 1321 | int need_requeue = 0; |
| 1261 | int ret; | ||
| 1262 | 1322 | ||
| 1263 | async_node = container_of(work, struct btrfs_async_delayed_node, work); | 1323 | async_node = container_of(work, struct btrfs_async_delayed_node, work); |
| 1264 | 1324 | ||
| @@ -1277,14 +1337,7 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work) | |||
| 1277 | block_rsv = trans->block_rsv; | 1337 | block_rsv = trans->block_rsv; |
| 1278 | trans->block_rsv = &root->fs_info->delayed_block_rsv; | 1338 | trans->block_rsv = &root->fs_info->delayed_block_rsv; |
| 1279 | 1339 | ||
| 1280 | ret = btrfs_insert_delayed_items(trans, path, root, delayed_node); | 1340 | __btrfs_commit_inode_delayed_items(trans, path, delayed_node); |
| 1281 | if (!ret) | ||
| 1282 | ret = btrfs_delete_delayed_items(trans, path, root, | ||
| 1283 | delayed_node); | ||
| 1284 | |||
| 1285 | if (!ret) | ||
| 1286 | btrfs_update_delayed_inode(trans, root, path, delayed_node); | ||
| 1287 | |||
| 1288 | /* | 1341 | /* |
| 1289 | * Maybe new delayed items have been inserted, so we need requeue | 1342 | * Maybe new delayed items have been inserted, so we need requeue |
| 1290 | * the work. Besides that, we must dequeue the empty delayed nodes | 1343 | * the work. Besides that, we must dequeue the empty delayed nodes |
