diff options
Diffstat (limited to 'fs/ocfs2/dlmglue.c')
| -rw-r--r-- | fs/ocfs2/dlmglue.c | 143 |
1 files changed, 126 insertions, 17 deletions
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index e335541727f9..27e43b0c0eae 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
| @@ -225,11 +225,17 @@ static struct ocfs2_lock_res_ops ocfs2_dentry_lops = { | |||
| 225 | .flags = 0, | 225 | .flags = 0, |
| 226 | }; | 226 | }; |
| 227 | 227 | ||
| 228 | static struct ocfs2_lock_res_ops ocfs2_inode_open_lops = { | ||
| 229 | .get_osb = ocfs2_get_inode_osb, | ||
| 230 | .flags = 0, | ||
| 231 | }; | ||
| 232 | |||
| 228 | static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres) | 233 | static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres) |
| 229 | { | 234 | { |
| 230 | return lockres->l_type == OCFS2_LOCK_TYPE_META || | 235 | return lockres->l_type == OCFS2_LOCK_TYPE_META || |
| 231 | lockres->l_type == OCFS2_LOCK_TYPE_DATA || | 236 | lockres->l_type == OCFS2_LOCK_TYPE_DATA || |
| 232 | lockres->l_type == OCFS2_LOCK_TYPE_RW; | 237 | lockres->l_type == OCFS2_LOCK_TYPE_RW || |
| 238 | lockres->l_type == OCFS2_LOCK_TYPE_OPEN; | ||
| 233 | } | 239 | } |
| 234 | 240 | ||
| 235 | static inline struct inode *ocfs2_lock_res_inode(struct ocfs2_lock_res *lockres) | 241 | static inline struct inode *ocfs2_lock_res_inode(struct ocfs2_lock_res *lockres) |
| @@ -373,6 +379,9 @@ void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res, | |||
| 373 | case OCFS2_LOCK_TYPE_DATA: | 379 | case OCFS2_LOCK_TYPE_DATA: |
| 374 | ops = &ocfs2_inode_data_lops; | 380 | ops = &ocfs2_inode_data_lops; |
| 375 | break; | 381 | break; |
| 382 | case OCFS2_LOCK_TYPE_OPEN: | ||
| 383 | ops = &ocfs2_inode_open_lops; | ||
| 384 | break; | ||
| 376 | default: | 385 | default: |
| 377 | mlog_bug_on_msg(1, "type: %d\n", type); | 386 | mlog_bug_on_msg(1, "type: %d\n", type); |
| 378 | ops = NULL; /* thanks, gcc */ | 387 | ops = NULL; /* thanks, gcc */ |
| @@ -1129,6 +1138,12 @@ int ocfs2_create_new_inode_locks(struct inode *inode) | |||
| 1129 | goto bail; | 1138 | goto bail; |
| 1130 | } | 1139 | } |
| 1131 | 1140 | ||
| 1141 | ret = ocfs2_create_new_lock(osb, &OCFS2_I(inode)->ip_open_lockres, 0, 0); | ||
| 1142 | if (ret) { | ||
| 1143 | mlog_errno(ret); | ||
| 1144 | goto bail; | ||
| 1145 | } | ||
| 1146 | |||
| 1132 | bail: | 1147 | bail: |
| 1133 | mlog_exit(ret); | 1148 | mlog_exit(ret); |
| 1134 | return ret; | 1149 | return ret; |
| @@ -1182,6 +1197,99 @@ void ocfs2_rw_unlock(struct inode *inode, int write) | |||
| 1182 | mlog_exit_void(); | 1197 | mlog_exit_void(); |
| 1183 | } | 1198 | } |
| 1184 | 1199 | ||
| 1200 | /* | ||
| 1201 | * ocfs2_open_lock always get PR mode lock. | ||
| 1202 | */ | ||
| 1203 | int ocfs2_open_lock(struct inode *inode) | ||
| 1204 | { | ||
| 1205 | int status = 0; | ||
| 1206 | struct ocfs2_lock_res *lockres; | ||
| 1207 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
| 1208 | |||
| 1209 | BUG_ON(!inode); | ||
| 1210 | |||
| 1211 | mlog_entry_void(); | ||
| 1212 | |||
| 1213 | mlog(0, "inode %llu take PRMODE open lock\n", | ||
| 1214 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | ||
| 1215 | |||
| 1216 | if (ocfs2_mount_local(osb)) | ||
| 1217 | goto out; | ||
| 1218 | |||
| 1219 | lockres = &OCFS2_I(inode)->ip_open_lockres; | ||
| 1220 | |||
| 1221 | status = ocfs2_cluster_lock(OCFS2_SB(inode->i_sb), lockres, | ||
| 1222 | LKM_PRMODE, 0, 0); | ||
| 1223 | if (status < 0) | ||
| 1224 | mlog_errno(status); | ||
| 1225 | |||
| 1226 | out: | ||
| 1227 | mlog_exit(status); | ||
| 1228 | return status; | ||
| 1229 | } | ||
| 1230 | |||
| 1231 | int ocfs2_try_open_lock(struct inode *inode, int write) | ||
| 1232 | { | ||
| 1233 | int status = 0, level; | ||
| 1234 | struct ocfs2_lock_res *lockres; | ||
| 1235 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
| 1236 | |||
| 1237 | BUG_ON(!inode); | ||
| 1238 | |||
| 1239 | mlog_entry_void(); | ||
| 1240 | |||
| 1241 | mlog(0, "inode %llu try to take %s open lock\n", | ||
| 1242 | (unsigned long long)OCFS2_I(inode)->ip_blkno, | ||
| 1243 | write ? "EXMODE" : "PRMODE"); | ||
| 1244 | |||
| 1245 | if (ocfs2_mount_local(osb)) | ||
| 1246 | goto out; | ||
| 1247 | |||
| 1248 | lockres = &OCFS2_I(inode)->ip_open_lockres; | ||
| 1249 | |||
| 1250 | level = write ? LKM_EXMODE : LKM_PRMODE; | ||
| 1251 | |||
| 1252 | /* | ||
| 1253 | * The file system may already holding a PRMODE/EXMODE open lock. | ||
| 1254 | * Since we pass LKM_NOQUEUE, the request won't block waiting on | ||
| 1255 | * other nodes and the -EAGAIN will indicate to the caller that | ||
| 1256 | * this inode is still in use. | ||
| 1257 | */ | ||
| 1258 | status = ocfs2_cluster_lock(OCFS2_SB(inode->i_sb), lockres, | ||
| 1259 | level, LKM_NOQUEUE, 0); | ||
| 1260 | |||
| 1261 | out: | ||
| 1262 | mlog_exit(status); | ||
| 1263 | return status; | ||
| 1264 | } | ||
| 1265 | |||
| 1266 | /* | ||
| 1267 | * ocfs2_open_unlock unlock PR and EX mode open locks. | ||
| 1268 | */ | ||
| 1269 | void ocfs2_open_unlock(struct inode *inode) | ||
| 1270 | { | ||
| 1271 | struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_open_lockres; | ||
| 1272 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
| 1273 | |||
| 1274 | mlog_entry_void(); | ||
| 1275 | |||
| 1276 | mlog(0, "inode %llu drop open lock\n", | ||
| 1277 | (unsigned long long)OCFS2_I(inode)->ip_blkno); | ||
| 1278 | |||
| 1279 | if (ocfs2_mount_local(osb)) | ||
| 1280 | goto out; | ||
| 1281 | |||
| 1282 | if(lockres->l_ro_holders) | ||
| 1283 | ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, | ||
| 1284 | LKM_PRMODE); | ||
| 1285 | if(lockres->l_ex_holders) | ||
| 1286 | ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, | ||
| 1287 | LKM_EXMODE); | ||
| 1288 | |||
| 1289 | out: | ||
| 1290 | mlog_exit_void(); | ||
| 1291 | } | ||
| 1292 | |||
| 1185 | int ocfs2_data_lock_full(struct inode *inode, | 1293 | int ocfs2_data_lock_full(struct inode *inode, |
| 1186 | int write, | 1294 | int write, |
| 1187 | int arg_flags) | 1295 | int arg_flags) |
| @@ -1387,8 +1495,7 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode) | |||
| 1387 | if (S_ISLNK(inode->i_mode) && !oi->ip_clusters) | 1495 | if (S_ISLNK(inode->i_mode) && !oi->ip_clusters) |
| 1388 | inode->i_blocks = 0; | 1496 | inode->i_blocks = 0; |
| 1389 | else | 1497 | else |
| 1390 | inode->i_blocks = | 1498 | inode->i_blocks = ocfs2_inode_sector_count(inode); |
| 1391 | ocfs2_align_bytes_to_sectors(i_size_read(inode)); | ||
| 1392 | 1499 | ||
| 1393 | inode->i_uid = be32_to_cpu(lvb->lvb_iuid); | 1500 | inode->i_uid = be32_to_cpu(lvb->lvb_iuid); |
| 1394 | inode->i_gid = be32_to_cpu(lvb->lvb_igid); | 1501 | inode->i_gid = be32_to_cpu(lvb->lvb_igid); |
| @@ -1479,12 +1586,15 @@ static int ocfs2_meta_lock_update(struct inode *inode, | |||
| 1479 | { | 1586 | { |
| 1480 | int status = 0; | 1587 | int status = 0; |
| 1481 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | 1588 | struct ocfs2_inode_info *oi = OCFS2_I(inode); |
| 1482 | struct ocfs2_lock_res *lockres = NULL; | 1589 | struct ocfs2_lock_res *lockres = &oi->ip_meta_lockres; |
| 1483 | struct ocfs2_dinode *fe; | 1590 | struct ocfs2_dinode *fe; |
| 1484 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 1591 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
| 1485 | 1592 | ||
| 1486 | mlog_entry_void(); | 1593 | mlog_entry_void(); |
| 1487 | 1594 | ||
| 1595 | if (ocfs2_mount_local(osb)) | ||
| 1596 | goto bail; | ||
| 1597 | |||
| 1488 | spin_lock(&oi->ip_lock); | 1598 | spin_lock(&oi->ip_lock); |
| 1489 | if (oi->ip_flags & OCFS2_INODE_DELETED) { | 1599 | if (oi->ip_flags & OCFS2_INODE_DELETED) { |
| 1490 | mlog(0, "Orphaned inode %llu was deleted while we " | 1600 | mlog(0, "Orphaned inode %llu was deleted while we " |
| @@ -1496,22 +1606,16 @@ static int ocfs2_meta_lock_update(struct inode *inode, | |||
| 1496 | } | 1606 | } |
| 1497 | spin_unlock(&oi->ip_lock); | 1607 | spin_unlock(&oi->ip_lock); |
| 1498 | 1608 | ||
| 1499 | if (!ocfs2_mount_local(osb)) { | 1609 | if (!ocfs2_should_refresh_lock_res(lockres)) |
| 1500 | lockres = &oi->ip_meta_lockres; | 1610 | goto bail; |
| 1501 | |||
| 1502 | if (!ocfs2_should_refresh_lock_res(lockres)) | ||
| 1503 | goto bail; | ||
| 1504 | } | ||
| 1505 | 1611 | ||
| 1506 | /* This will discard any caching information we might have had | 1612 | /* This will discard any caching information we might have had |
| 1507 | * for the inode metadata. */ | 1613 | * for the inode metadata. */ |
| 1508 | ocfs2_metadata_cache_purge(inode); | 1614 | ocfs2_metadata_cache_purge(inode); |
| 1509 | 1615 | ||
| 1510 | /* will do nothing for inode types that don't use the extent | ||
| 1511 | * map (directories, bitmap files, etc) */ | ||
| 1512 | ocfs2_extent_map_trunc(inode, 0); | 1616 | ocfs2_extent_map_trunc(inode, 0); |
| 1513 | 1617 | ||
| 1514 | if (lockres && ocfs2_meta_lvb_is_trustable(inode, lockres)) { | 1618 | if (ocfs2_meta_lvb_is_trustable(inode, lockres)) { |
| 1515 | mlog(0, "Trusting LVB on inode %llu\n", | 1619 | mlog(0, "Trusting LVB on inode %llu\n", |
| 1516 | (unsigned long long)oi->ip_blkno); | 1620 | (unsigned long long)oi->ip_blkno); |
| 1517 | ocfs2_refresh_inode_from_lvb(inode); | 1621 | ocfs2_refresh_inode_from_lvb(inode); |
| @@ -1558,8 +1662,7 @@ static int ocfs2_meta_lock_update(struct inode *inode, | |||
| 1558 | 1662 | ||
| 1559 | status = 0; | 1663 | status = 0; |
| 1560 | bail_refresh: | 1664 | bail_refresh: |
| 1561 | if (lockres) | 1665 | ocfs2_complete_lock_res_refresh(lockres, status); |
| 1562 | ocfs2_complete_lock_res_refresh(lockres, status); | ||
| 1563 | bail: | 1666 | bail: |
| 1564 | mlog_exit(status); | 1667 | mlog_exit(status); |
| 1565 | return status; | 1668 | return status; |
| @@ -1630,7 +1733,6 @@ int ocfs2_meta_lock_full(struct inode *inode, | |||
| 1630 | wait_event(osb->recovery_event, | 1733 | wait_event(osb->recovery_event, |
| 1631 | ocfs2_node_map_is_empty(osb, &osb->recovery_map)); | 1734 | ocfs2_node_map_is_empty(osb, &osb->recovery_map)); |
| 1632 | 1735 | ||
| 1633 | acquired = 0; | ||
| 1634 | lockres = &OCFS2_I(inode)->ip_meta_lockres; | 1736 | lockres = &OCFS2_I(inode)->ip_meta_lockres; |
| 1635 | level = ex ? LKM_EXMODE : LKM_PRMODE; | 1737 | level = ex ? LKM_EXMODE : LKM_PRMODE; |
| 1636 | dlm_flags = 0; | 1738 | dlm_flags = 0; |
| @@ -2458,13 +2560,20 @@ int ocfs2_drop_inode_locks(struct inode *inode) | |||
| 2458 | * ocfs2_clear_inode has done it for us. */ | 2560 | * ocfs2_clear_inode has done it for us. */ |
| 2459 | 2561 | ||
| 2460 | err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb), | 2562 | err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb), |
| 2461 | &OCFS2_I(inode)->ip_data_lockres); | 2563 | &OCFS2_I(inode)->ip_open_lockres); |
| 2462 | if (err < 0) | 2564 | if (err < 0) |
| 2463 | mlog_errno(err); | 2565 | mlog_errno(err); |
| 2464 | 2566 | ||
| 2465 | status = err; | 2567 | status = err; |
| 2466 | 2568 | ||
| 2467 | err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb), | 2569 | err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb), |
| 2570 | &OCFS2_I(inode)->ip_data_lockres); | ||
| 2571 | if (err < 0) | ||
| 2572 | mlog_errno(err); | ||
| 2573 | if (err < 0 && !status) | ||
| 2574 | status = err; | ||
| 2575 | |||
| 2576 | err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb), | ||
| 2468 | &OCFS2_I(inode)->ip_meta_lockres); | 2577 | &OCFS2_I(inode)->ip_meta_lockres); |
| 2469 | if (err < 0) | 2578 | if (err < 0) |
| 2470 | mlog_errno(err); | 2579 | mlog_errno(err); |
