diff options
Diffstat (limited to 'fs/gfs2/ops_inode.c')
-rw-r--r-- | fs/gfs2/ops_inode.c | 63 |
1 files changed, 47 insertions, 16 deletions
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index 636dda4c7d38..60f47bf2e8e8 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c | |||
@@ -264,13 +264,23 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry) | |||
264 | struct gfs2_inode *dip = GFS2_I(dir); | 264 | struct gfs2_inode *dip = GFS2_I(dir); |
265 | struct gfs2_sbd *sdp = GFS2_SB(dir); | 265 | struct gfs2_sbd *sdp = GFS2_SB(dir); |
266 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); | 266 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); |
267 | struct gfs2_holder ghs[2]; | 267 | struct gfs2_holder ghs[3]; |
268 | struct gfs2_rgrpd *rgd; | ||
269 | struct gfs2_holder ri_gh; | ||
268 | int error; | 270 | int error; |
269 | 271 | ||
272 | error = gfs2_rindex_hold(sdp, &ri_gh); | ||
273 | if (error) | ||
274 | return error; | ||
275 | |||
270 | gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); | 276 | gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); |
271 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); | 277 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); |
272 | 278 | ||
273 | error = gfs2_glock_nq_m(2, ghs); | 279 | rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr); |
280 | gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2); | ||
281 | |||
282 | |||
283 | error = gfs2_glock_nq_m(3, ghs); | ||
274 | if (error) | 284 | if (error) |
275 | goto out; | 285 | goto out; |
276 | 286 | ||
@@ -291,10 +301,12 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry) | |||
291 | out_end_trans: | 301 | out_end_trans: |
292 | gfs2_trans_end(sdp); | 302 | gfs2_trans_end(sdp); |
293 | out_gunlock: | 303 | out_gunlock: |
294 | gfs2_glock_dq_m(2, ghs); | 304 | gfs2_glock_dq_m(3, ghs); |
295 | out: | 305 | out: |
296 | gfs2_holder_uninit(ghs); | 306 | gfs2_holder_uninit(ghs); |
297 | gfs2_holder_uninit(ghs + 1); | 307 | gfs2_holder_uninit(ghs + 1); |
308 | gfs2_holder_uninit(ghs + 2); | ||
309 | gfs2_glock_dq_uninit(&ri_gh); | ||
298 | return error; | 310 | return error; |
299 | } | 311 | } |
300 | 312 | ||
@@ -449,13 +461,22 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry) | |||
449 | struct gfs2_inode *dip = GFS2_I(dir); | 461 | struct gfs2_inode *dip = GFS2_I(dir); |
450 | struct gfs2_sbd *sdp = GFS2_SB(dir); | 462 | struct gfs2_sbd *sdp = GFS2_SB(dir); |
451 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); | 463 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); |
452 | struct gfs2_holder ghs[2]; | 464 | struct gfs2_holder ghs[3]; |
465 | struct gfs2_rgrpd *rgd; | ||
466 | struct gfs2_holder ri_gh; | ||
453 | int error; | 467 | int error; |
454 | 468 | ||
469 | |||
470 | error = gfs2_rindex_hold(sdp, &ri_gh); | ||
471 | if (error) | ||
472 | return error; | ||
455 | gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); | 473 | gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs); |
456 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); | 474 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1); |
457 | 475 | ||
458 | error = gfs2_glock_nq_m(2, ghs); | 476 | rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr); |
477 | gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2); | ||
478 | |||
479 | error = gfs2_glock_nq_m(3, ghs); | ||
459 | if (error) | 480 | if (error) |
460 | goto out; | 481 | goto out; |
461 | 482 | ||
@@ -483,10 +504,12 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry) | |||
483 | gfs2_trans_end(sdp); | 504 | gfs2_trans_end(sdp); |
484 | 505 | ||
485 | out_gunlock: | 506 | out_gunlock: |
486 | gfs2_glock_dq_m(2, ghs); | 507 | gfs2_glock_dq_m(3, ghs); |
487 | out: | 508 | out: |
488 | gfs2_holder_uninit(ghs); | 509 | gfs2_holder_uninit(ghs); |
489 | gfs2_holder_uninit(ghs + 1); | 510 | gfs2_holder_uninit(ghs + 1); |
511 | gfs2_holder_uninit(ghs + 2); | ||
512 | gfs2_glock_dq_uninit(&ri_gh); | ||
490 | return error; | 513 | return error; |
491 | } | 514 | } |
492 | 515 | ||
@@ -547,7 +570,8 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
547 | struct gfs2_inode *ip = GFS2_I(odentry->d_inode); | 570 | struct gfs2_inode *ip = GFS2_I(odentry->d_inode); |
548 | struct gfs2_inode *nip = NULL; | 571 | struct gfs2_inode *nip = NULL; |
549 | struct gfs2_sbd *sdp = GFS2_SB(odir); | 572 | struct gfs2_sbd *sdp = GFS2_SB(odir); |
550 | struct gfs2_holder ghs[4], r_gh; | 573 | struct gfs2_holder ghs[5], r_gh; |
574 | struct gfs2_rgrpd *nrgd; | ||
551 | unsigned int num_gh; | 575 | unsigned int num_gh; |
552 | int dir_rename = 0; | 576 | int dir_rename = 0; |
553 | int alloc_required; | 577 | int alloc_required; |
@@ -587,6 +611,13 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
587 | if (nip) { | 611 | if (nip) { |
588 | gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh); | 612 | gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh); |
589 | num_gh++; | 613 | num_gh++; |
614 | /* grab the resource lock for unlink flag twiddling | ||
615 | * this is the case of the target file already existing | ||
616 | * so we unlink before doing the rename | ||
617 | */ | ||
618 | nrgd = gfs2_blk2rgrpd(sdp, nip->i_num.no_addr); | ||
619 | if (nrgd) | ||
620 | gfs2_holder_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh++); | ||
590 | } | 621 | } |
591 | 622 | ||
592 | error = gfs2_glock_nq_m(num_gh, ghs); | 623 | error = gfs2_glock_nq_m(num_gh, ghs); |
@@ -684,12 +715,12 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
684 | error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + | 715 | error = gfs2_trans_begin(sdp, sdp->sd_max_dirres + |
685 | al->al_rgd->rd_ri.ri_length + | 716 | al->al_rgd->rd_ri.ri_length + |
686 | 4 * RES_DINODE + 4 * RES_LEAF + | 717 | 4 * RES_DINODE + 4 * RES_LEAF + |
687 | RES_STATFS + RES_QUOTA, 0); | 718 | RES_STATFS + RES_QUOTA + 4, 0); |
688 | if (error) | 719 | if (error) |
689 | goto out_ipreserv; | 720 | goto out_ipreserv; |
690 | } else { | 721 | } else { |
691 | error = gfs2_trans_begin(sdp, 4 * RES_DINODE + | 722 | error = gfs2_trans_begin(sdp, 4 * RES_DINODE + |
692 | 5 * RES_LEAF, 0); | 723 | 5 * RES_LEAF + 4, 0); |
693 | if (error) | 724 | if (error) |
694 | goto out_gunlock; | 725 | goto out_gunlock; |
695 | } | 726 | } |
@@ -728,7 +759,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
728 | error = gfs2_meta_inode_buffer(ip, &dibh); | 759 | error = gfs2_meta_inode_buffer(ip, &dibh); |
729 | if (error) | 760 | if (error) |
730 | goto out_end_trans; | 761 | goto out_end_trans; |
731 | ip->i_inode.i_ctime.tv_sec = get_seconds(); | 762 | ip->i_inode.i_ctime = CURRENT_TIME_SEC; |
732 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 763 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
733 | gfs2_dinode_out(ip, dibh->b_data); | 764 | gfs2_dinode_out(ip, dibh->b_data); |
734 | brelse(dibh); | 765 | brelse(dibh); |
@@ -1018,7 +1049,7 @@ static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
1018 | } | 1049 | } |
1019 | 1050 | ||
1020 | generic_fillattr(inode, stat); | 1051 | generic_fillattr(inode, stat); |
1021 | if (unlock); | 1052 | if (unlock) |
1022 | gfs2_glock_dq_uninit(&gh); | 1053 | gfs2_glock_dq_uninit(&gh); |
1023 | 1054 | ||
1024 | return 0; | 1055 | return 0; |
@@ -1084,7 +1115,7 @@ static int gfs2_removexattr(struct dentry *dentry, const char *name) | |||
1084 | return gfs2_ea_remove(GFS2_I(dentry->d_inode), &er); | 1115 | return gfs2_ea_remove(GFS2_I(dentry->d_inode), &er); |
1085 | } | 1116 | } |
1086 | 1117 | ||
1087 | struct inode_operations gfs2_file_iops = { | 1118 | const struct inode_operations gfs2_file_iops = { |
1088 | .permission = gfs2_permission, | 1119 | .permission = gfs2_permission, |
1089 | .setattr = gfs2_setattr, | 1120 | .setattr = gfs2_setattr, |
1090 | .getattr = gfs2_getattr, | 1121 | .getattr = gfs2_getattr, |
@@ -1094,7 +1125,7 @@ struct inode_operations gfs2_file_iops = { | |||
1094 | .removexattr = gfs2_removexattr, | 1125 | .removexattr = gfs2_removexattr, |
1095 | }; | 1126 | }; |
1096 | 1127 | ||
1097 | struct inode_operations gfs2_dev_iops = { | 1128 | const struct inode_operations gfs2_dev_iops = { |
1098 | .permission = gfs2_permission, | 1129 | .permission = gfs2_permission, |
1099 | .setattr = gfs2_setattr, | 1130 | .setattr = gfs2_setattr, |
1100 | .getattr = gfs2_getattr, | 1131 | .getattr = gfs2_getattr, |
@@ -1104,7 +1135,7 @@ struct inode_operations gfs2_dev_iops = { | |||
1104 | .removexattr = gfs2_removexattr, | 1135 | .removexattr = gfs2_removexattr, |
1105 | }; | 1136 | }; |
1106 | 1137 | ||
1107 | struct inode_operations gfs2_dir_iops = { | 1138 | const struct inode_operations gfs2_dir_iops = { |
1108 | .create = gfs2_create, | 1139 | .create = gfs2_create, |
1109 | .lookup = gfs2_lookup, | 1140 | .lookup = gfs2_lookup, |
1110 | .link = gfs2_link, | 1141 | .link = gfs2_link, |
@@ -1123,7 +1154,7 @@ struct inode_operations gfs2_dir_iops = { | |||
1123 | .removexattr = gfs2_removexattr, | 1154 | .removexattr = gfs2_removexattr, |
1124 | }; | 1155 | }; |
1125 | 1156 | ||
1126 | struct inode_operations gfs2_symlink_iops = { | 1157 | const struct inode_operations gfs2_symlink_iops = { |
1127 | .readlink = gfs2_readlink, | 1158 | .readlink = gfs2_readlink, |
1128 | .follow_link = gfs2_follow_link, | 1159 | .follow_link = gfs2_follow_link, |
1129 | .permission = gfs2_permission, | 1160 | .permission = gfs2_permission, |