diff options
Diffstat (limited to 'fs/ocfs2/vote.c')
| -rw-r--r-- | fs/ocfs2/vote.c | 180 |
1 files changed, 2 insertions, 178 deletions
diff --git a/fs/ocfs2/vote.c b/fs/ocfs2/vote.c index cf70fe2075b8..5b4dca79990b 100644 --- a/fs/ocfs2/vote.c +++ b/fs/ocfs2/vote.c | |||
| @@ -74,9 +74,6 @@ struct ocfs2_vote_msg | |||
| 74 | __be32 v_orphaned_slot; /* Used during delete votes */ | 74 | __be32 v_orphaned_slot; /* Used during delete votes */ |
| 75 | __be32 v_nlink; /* Used during unlink votes */ | 75 | __be32 v_nlink; /* Used during unlink votes */ |
| 76 | } md1; /* Message type dependant 1 */ | 76 | } md1; /* Message type dependant 1 */ |
| 77 | __be32 v_unlink_namelen; | ||
| 78 | __be64 v_unlink_parent; | ||
| 79 | u8 v_unlink_dirent[OCFS2_VOTE_FILENAME_LEN]; | ||
| 80 | }; | 77 | }; |
| 81 | 78 | ||
| 82 | /* Responses are given these values to maintain backwards | 79 | /* Responses are given these values to maintain backwards |
| @@ -100,8 +97,6 @@ struct ocfs2_vote_work { | |||
| 100 | enum ocfs2_vote_request { | 97 | enum ocfs2_vote_request { |
| 101 | OCFS2_VOTE_REQ_INVALID = 0, | 98 | OCFS2_VOTE_REQ_INVALID = 0, |
| 102 | OCFS2_VOTE_REQ_DELETE, | 99 | OCFS2_VOTE_REQ_DELETE, |
| 103 | OCFS2_VOTE_REQ_UNLINK, | ||
| 104 | OCFS2_VOTE_REQ_RENAME, | ||
| 105 | OCFS2_VOTE_REQ_MOUNT, | 100 | OCFS2_VOTE_REQ_MOUNT, |
| 106 | OCFS2_VOTE_REQ_UMOUNT, | 101 | OCFS2_VOTE_REQ_UMOUNT, |
| 107 | OCFS2_VOTE_REQ_LAST | 102 | OCFS2_VOTE_REQ_LAST |
| @@ -261,103 +256,13 @@ done: | |||
| 261 | return response; | 256 | return response; |
| 262 | } | 257 | } |
| 263 | 258 | ||
| 264 | static int ocfs2_match_dentry(struct dentry *dentry, | ||
| 265 | u64 parent_blkno, | ||
| 266 | unsigned int namelen, | ||
| 267 | const char *name) | ||
| 268 | { | ||
| 269 | struct inode *parent; | ||
| 270 | |||
| 271 | if (!dentry->d_parent) { | ||
| 272 | mlog(0, "Detached from parent.\n"); | ||
| 273 | return 0; | ||
| 274 | } | ||
| 275 | |||
| 276 | parent = dentry->d_parent->d_inode; | ||
| 277 | /* Negative parent dentry? */ | ||
| 278 | if (!parent) | ||
| 279 | return 0; | ||
| 280 | |||
| 281 | /* Name is in a different directory. */ | ||
| 282 | if (OCFS2_I(parent)->ip_blkno != parent_blkno) | ||
| 283 | return 0; | ||
| 284 | |||
| 285 | if (dentry->d_name.len != namelen) | ||
| 286 | return 0; | ||
| 287 | |||
| 288 | /* comparison above guarantees this is safe. */ | ||
| 289 | if (memcmp(dentry->d_name.name, name, namelen)) | ||
| 290 | return 0; | ||
| 291 | |||
| 292 | return 1; | ||
| 293 | } | ||
| 294 | |||
| 295 | static void ocfs2_process_dentry_request(struct inode *inode, | ||
| 296 | int rename, | ||
| 297 | unsigned int new_nlink, | ||
| 298 | u64 parent_blkno, | ||
| 299 | unsigned int namelen, | ||
| 300 | const char *name) | ||
| 301 | { | ||
| 302 | struct dentry *dentry = NULL; | ||
| 303 | struct list_head *p; | ||
| 304 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | ||
| 305 | |||
| 306 | mlog(0, "parent %llu, namelen = %u, name = %.*s\n", | ||
| 307 | (unsigned long long)parent_blkno, namelen, namelen, name); | ||
| 308 | |||
| 309 | spin_lock(&dcache_lock); | ||
| 310 | |||
| 311 | /* Another node is removing this name from the system. It is | ||
| 312 | * up to us to find the corresponding dentry and if it exists, | ||
| 313 | * unhash it from the dcache. */ | ||
| 314 | list_for_each(p, &inode->i_dentry) { | ||
| 315 | dentry = list_entry(p, struct dentry, d_alias); | ||
| 316 | |||
| 317 | if (ocfs2_match_dentry(dentry, parent_blkno, namelen, name)) { | ||
| 318 | mlog(0, "dentry found: %.*s\n", | ||
| 319 | dentry->d_name.len, dentry->d_name.name); | ||
| 320 | |||
| 321 | dget_locked(dentry); | ||
| 322 | break; | ||
| 323 | } | ||
| 324 | |||
| 325 | dentry = NULL; | ||
| 326 | } | ||
| 327 | |||
| 328 | spin_unlock(&dcache_lock); | ||
| 329 | |||
| 330 | if (dentry) { | ||
| 331 | d_delete(dentry); | ||
| 332 | dput(dentry); | ||
| 333 | } | ||
| 334 | |||
| 335 | /* rename votes don't send link counts */ | ||
| 336 | if (!rename) { | ||
| 337 | mlog(0, "new_nlink = %u\n", new_nlink); | ||
| 338 | |||
| 339 | /* We don't have the proper locks here to directly | ||
| 340 | * change i_nlink and besides, the vote is sent | ||
| 341 | * *before* the operation so it may have failed on the | ||
| 342 | * other node. This passes a hint to ocfs2_drop_inode | ||
| 343 | * to force ocfs2_delete_inode, who will take the | ||
| 344 | * proper cluster locks to sort things out. */ | ||
| 345 | if (new_nlink == 0) { | ||
| 346 | spin_lock(&oi->ip_lock); | ||
| 347 | oi->ip_flags |= OCFS2_INODE_MAYBE_ORPHANED; | ||
| 348 | spin_unlock(&OCFS2_I(inode)->ip_lock); | ||
| 349 | } | ||
| 350 | } | ||
| 351 | } | ||
| 352 | |||
| 353 | static void ocfs2_process_vote(struct ocfs2_super *osb, | 259 | static void ocfs2_process_vote(struct ocfs2_super *osb, |
| 354 | struct ocfs2_vote_msg *msg) | 260 | struct ocfs2_vote_msg *msg) |
| 355 | { | 261 | { |
| 356 | int net_status, vote_response; | 262 | int net_status, vote_response; |
| 357 | int orphaned_slot = 0; | 263 | int orphaned_slot = 0; |
| 358 | int rename = 0; | 264 | unsigned int node_num, generation; |
| 359 | unsigned int node_num, generation, new_nlink, namelen; | 265 | u64 blkno; |
| 360 | u64 blkno, parent_blkno; | ||
| 361 | enum ocfs2_vote_request request; | 266 | enum ocfs2_vote_request request; |
| 362 | struct inode *inode = NULL; | 267 | struct inode *inode = NULL; |
| 363 | struct ocfs2_msg_hdr *hdr = &msg->v_hdr; | 268 | struct ocfs2_msg_hdr *hdr = &msg->v_hdr; |
| @@ -437,18 +342,6 @@ static void ocfs2_process_vote(struct ocfs2_super *osb, | |||
| 437 | vote_response = ocfs2_process_delete_request(inode, | 342 | vote_response = ocfs2_process_delete_request(inode, |
| 438 | &orphaned_slot); | 343 | &orphaned_slot); |
| 439 | break; | 344 | break; |
| 440 | case OCFS2_VOTE_REQ_RENAME: | ||
| 441 | rename = 1; | ||
| 442 | /* fall through */ | ||
| 443 | case OCFS2_VOTE_REQ_UNLINK: | ||
| 444 | parent_blkno = be64_to_cpu(msg->v_unlink_parent); | ||
| 445 | namelen = be32_to_cpu(msg->v_unlink_namelen); | ||
| 446 | /* new_nlink will be ignored in case of a rename vote */ | ||
| 447 | new_nlink = be32_to_cpu(msg->md1.v_nlink); | ||
| 448 | ocfs2_process_dentry_request(inode, rename, new_nlink, | ||
| 449 | parent_blkno, namelen, | ||
| 450 | msg->v_unlink_dirent); | ||
| 451 | break; | ||
| 452 | default: | 345 | default: |
| 453 | mlog(ML_ERROR, "node %u, invalid request: %u\n", | 346 | mlog(ML_ERROR, "node %u, invalid request: %u\n", |
| 454 | node_num, request); | 347 | node_num, request); |
| @@ -889,75 +782,6 @@ int ocfs2_request_delete_vote(struct inode *inode) | |||
| 889 | return status; | 782 | return status; |
| 890 | } | 783 | } |
| 891 | 784 | ||
| 892 | static void ocfs2_setup_unlink_vote(struct ocfs2_vote_msg *request, | ||
| 893 | struct dentry *dentry) | ||
| 894 | { | ||
| 895 | struct inode *parent = dentry->d_parent->d_inode; | ||
| 896 | |||
| 897 | /* We need some values which will uniquely identify a dentry | ||
| 898 | * on the other nodes so that they can find it and run | ||
| 899 | * d_delete against it. Parent directory block and full name | ||
| 900 | * should suffice. */ | ||
| 901 | |||
| 902 | mlog(0, "unlink/rename request: parent: %llu name: %.*s\n", | ||
| 903 | (unsigned long long)OCFS2_I(parent)->ip_blkno, dentry->d_name.len, | ||
| 904 | dentry->d_name.name); | ||
| 905 | |||
| 906 | request->v_unlink_parent = cpu_to_be64(OCFS2_I(parent)->ip_blkno); | ||
| 907 | request->v_unlink_namelen = cpu_to_be32(dentry->d_name.len); | ||
| 908 | memcpy(request->v_unlink_dirent, dentry->d_name.name, | ||
| 909 | dentry->d_name.len); | ||
| 910 | } | ||
| 911 | |||
| 912 | int ocfs2_request_unlink_vote(struct inode *inode, | ||
| 913 | struct dentry *dentry, | ||
| 914 | unsigned int nlink) | ||
| 915 | { | ||
| 916 | int status; | ||
| 917 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
| 918 | struct ocfs2_vote_msg *request; | ||
| 919 | |||
| 920 | if (dentry->d_name.len > OCFS2_VOTE_FILENAME_LEN) | ||
| 921 | return -ENAMETOOLONG; | ||
| 922 | |||
| 923 | status = -ENOMEM; | ||
| 924 | request = ocfs2_new_vote_request(osb, OCFS2_I(inode)->ip_blkno, | ||
| 925 | inode->i_generation, | ||
| 926 | OCFS2_VOTE_REQ_UNLINK, nlink); | ||
| 927 | if (request) { | ||
| 928 | ocfs2_setup_unlink_vote(request, dentry); | ||
| 929 | |||
| 930 | status = ocfs2_request_vote(inode, request, NULL); | ||
| 931 | |||
| 932 | kfree(request); | ||
| 933 | } | ||
| 934 | return status; | ||
| 935 | } | ||
| 936 | |||
| 937 | int ocfs2_request_rename_vote(struct inode *inode, | ||
| 938 | struct dentry *dentry) | ||
| 939 | { | ||
| 940 | int status; | ||
| 941 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
| 942 | struct ocfs2_vote_msg *request; | ||
| 943 | |||
| 944 | if (dentry->d_name.len > OCFS2_VOTE_FILENAME_LEN) | ||
| 945 | return -ENAMETOOLONG; | ||
| 946 | |||
| 947 | status = -ENOMEM; | ||
| 948 | request = ocfs2_new_vote_request(osb, OCFS2_I(inode)->ip_blkno, | ||
| 949 | inode->i_generation, | ||
| 950 | OCFS2_VOTE_REQ_RENAME, 0); | ||
| 951 | if (request) { | ||
| 952 | ocfs2_setup_unlink_vote(request, dentry); | ||
| 953 | |||
| 954 | status = ocfs2_request_vote(inode, request, NULL); | ||
| 955 | |||
| 956 | kfree(request); | ||
| 957 | } | ||
| 958 | return status; | ||
| 959 | } | ||
| 960 | |||
| 961 | int ocfs2_request_mount_vote(struct ocfs2_super *osb) | 785 | int ocfs2_request_mount_vote(struct ocfs2_super *osb) |
| 962 | { | 786 | { |
| 963 | int status; | 787 | int status; |
