aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/gfs2/dir.c5
-rw-r--r--fs/gfs2/dir.h2
-rw-r--r--fs/gfs2/ops_inode.c221
3 files changed, 71 insertions, 157 deletions
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index f7a31374ff82..410265151ad1 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -1669,8 +1669,9 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
1669 * Returns: 0 on success, error code on failure 1669 * Returns: 0 on success, error code on failure
1670 */ 1670 */
1671 1671
1672int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name) 1672int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry)
1673{ 1673{
1674 const struct qstr *name = &dentry->d_name;
1674 struct gfs2_dirent *dent, *prev = NULL; 1675 struct gfs2_dirent *dent, *prev = NULL;
1675 struct buffer_head *bh; 1676 struct buffer_head *bh;
1676 int error; 1677 int error;
@@ -1711,6 +1712,8 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name)
1711 gfs2_trans_add_bh(dip->i_gl, bh, 1); 1712 gfs2_trans_add_bh(dip->i_gl, bh, 1);
1712 dip->i_entries--; 1713 dip->i_entries--;
1713 dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME; 1714 dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME;
1715 if (S_ISDIR(dentry->d_inode->i_mode))
1716 drop_nlink(&dip->i_inode);
1714 gfs2_dinode_out(dip, bh->b_data); 1717 gfs2_dinode_out(dip, bh->b_data);
1715 brelse(bh); 1718 brelse(bh);
1716 mark_inode_dirty(&dip->i_inode); 1719 mark_inode_dirty(&dip->i_inode);
diff --git a/fs/gfs2/dir.h b/fs/gfs2/dir.h
index a98f644bd3df..66831f1d23ea 100644
--- a/fs/gfs2/dir.h
+++ b/fs/gfs2/dir.h
@@ -23,7 +23,7 @@ extern int gfs2_dir_check(struct inode *dir, const struct qstr *filename,
23 const struct gfs2_inode *ip); 23 const struct gfs2_inode *ip);
24extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename, 24extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
25 const struct gfs2_inode *ip, unsigned int type); 25 const struct gfs2_inode *ip, unsigned int type);
26extern int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename); 26extern int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry);
27extern int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, 27extern int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
28 filldir_t filldir); 28 filldir_t filldir);
29extern int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, 29extern int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index acb6f69b02ed..765da06c8f55 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -312,11 +312,52 @@ static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
312} 312}
313 313
314/** 314/**
315 * gfs2_unlink - Unlink a file 315 * gfs2_unlink_inode - Removes an inode from its parent dir and unlinks it
316 * @dir: The inode of the directory containing the file to unlink 316 * @dip: The parent directory
317 * @name: The name of the entry in the parent directory
318 * @bh: The inode buffer for the inode to be removed
319 * @inode: The inode to be removed
320 *
321 * Called with all the locks and in a transaction. This will only be
322 * called for a directory after it has been checked to ensure it is empty.
323 *
324 * Returns: 0 on success, or an error
325 */
326
327static int gfs2_unlink_inode(struct gfs2_inode *dip,
328 const struct dentry *dentry,
329 struct buffer_head *bh)
330{
331 struct inode *inode = dentry->d_inode;
332 struct gfs2_inode *ip = GFS2_I(inode);
333 int error;
334
335 error = gfs2_dir_del(dip, dentry);
336 if (error)
337 return error;
338
339 ip->i_entries = 0;
340 inode->i_ctime = CURRENT_TIME;
341 if (S_ISDIR(inode->i_mode))
342 clear_nlink(inode);
343 else
344 drop_nlink(inode);
345 gfs2_trans_add_bh(ip->i_gl, bh, 1);
346 gfs2_dinode_out(ip, bh->b_data);
347 mark_inode_dirty(inode);
348 if (inode->i_nlink == 0)
349 gfs2_unlink_di(inode);
350 return 0;
351}
352
353
354/**
355 * gfs2_unlink - Unlink an inode (this does rmdir as well)
356 * @dir: The inode of the directory containing the inode to unlink
317 * @dentry: The file itself 357 * @dentry: The file itself
318 * 358 *
319 * Unlink a file. Call gfs2_unlinki() 359 * This routine uses the type of the inode as a flag to figure out
360 * whether this is an unlink or an rmdir.
320 * 361 *
321 * Returns: errno 362 * Returns: errno
322 */ 363 */
@@ -325,7 +366,9 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
325{ 366{
326 struct gfs2_inode *dip = GFS2_I(dir); 367 struct gfs2_inode *dip = GFS2_I(dir);
327 struct gfs2_sbd *sdp = GFS2_SB(dir); 368 struct gfs2_sbd *sdp = GFS2_SB(dir);
328 struct gfs2_inode *ip = GFS2_I(dentry->d_inode); 369 struct inode *inode = dentry->d_inode;
370 struct gfs2_inode *ip = GFS2_I(inode);
371 struct buffer_head *bh;
329 struct gfs2_holder ghs[3]; 372 struct gfs2_holder ghs[3];
330 struct gfs2_rgrpd *rgd; 373 struct gfs2_rgrpd *rgd;
331 struct gfs2_holder ri_gh; 374 struct gfs2_holder ri_gh;
@@ -351,9 +394,15 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
351 goto out_child; 394 goto out_child;
352 395
353 error = -ENOENT; 396 error = -ENOENT;
354 if (ip->i_inode.i_nlink == 0) 397 if (inode->i_nlink == 0)
355 goto out_rgrp; 398 goto out_rgrp;
356 399
400 if (S_ISDIR(inode->i_mode)) {
401 error = -ENOTEMPTY;
402 if (ip->i_entries > 2 || inode->i_nlink > 2)
403 goto out_rgrp;
404 }
405
357 error = gfs2_glock_nq(ghs + 2); /* rgrp */ 406 error = gfs2_glock_nq(ghs + 2); /* rgrp */
358 if (error) 407 if (error)
359 goto out_rgrp; 408 goto out_rgrp;
@@ -362,15 +411,16 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
362 if (error) 411 if (error)
363 goto out_gunlock; 412 goto out_gunlock;
364 413
365 error = gfs2_trans_begin(sdp, 2*RES_DINODE + RES_LEAF + RES_RG_BIT, 0); 414 error = gfs2_trans_begin(sdp, 2*RES_DINODE + 3*RES_LEAF + RES_RG_BIT, 0);
366 if (error) 415 if (error)
367 goto out_gunlock; 416 goto out_gunlock;
368 417
369 error = gfs2_dir_del(dip, &dentry->d_name); 418 error = gfs2_meta_inode_buffer(ip, &bh);
370 if (error) 419 if (error)
371 goto out_end_trans; 420 goto out_end_trans;
372 421
373 error = gfs2_change_nlink(ip, -1); 422 error = gfs2_unlink_inode(dip, dentry, bh);
423 brelse(bh);
374 424
375out_end_trans: 425out_end_trans:
376 gfs2_trans_end(sdp); 426 gfs2_trans_end(sdp);
@@ -522,138 +572,6 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode)
522} 572}
523 573
524/** 574/**
525 * gfs2_rmdiri - Remove a directory
526 * @dip: The parent directory of the directory to be removed
527 * @name: The name of the directory to be removed
528 * @ip: The GFS2 inode of the directory to be removed
529 *
530 * Assumes Glocks on dip and ip are held
531 *
532 * Returns: errno
533 */
534
535static int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
536 struct gfs2_inode *ip)
537{
538 int error;
539
540 if (ip->i_entries != 2) {
541 if (gfs2_consist_inode(ip))
542 gfs2_dinode_print(ip);
543 return -EIO;
544 }
545
546 error = gfs2_dir_del(dip, name);
547 if (error)
548 return error;
549
550 error = gfs2_change_nlink(dip, -1);
551 if (error)
552 return error;
553
554 error = gfs2_dir_del(ip, &gfs2_qdot);
555 if (error)
556 return error;
557
558 error = gfs2_dir_del(ip, &gfs2_qdotdot);
559 if (error)
560 return error;
561
562 /* It looks odd, but it really should be done twice */
563 error = gfs2_change_nlink(ip, -1);
564 if (error)
565 return error;
566
567 error = gfs2_change_nlink(ip, -1);
568 if (error)
569 return error;
570
571 return error;
572}
573
574/**
575 * gfs2_rmdir - Remove a directory
576 * @dir: The parent directory of the directory to be removed
577 * @dentry: The dentry of the directory to remove
578 *
579 * Remove a directory. Call gfs2_rmdiri()
580 *
581 * Returns: errno
582 */
583
584static int gfs2_rmdir(struct inode *dir, struct dentry *dentry)
585{
586 struct gfs2_inode *dip = GFS2_I(dir);
587 struct gfs2_sbd *sdp = GFS2_SB(dir);
588 struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
589 struct gfs2_holder ghs[3];
590 struct gfs2_rgrpd *rgd;
591 struct gfs2_holder ri_gh;
592 int error;
593
594 error = gfs2_rindex_hold(sdp, &ri_gh);
595 if (error)
596 return error;
597 gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
598 gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1);
599
600 rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr);
601 gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2);
602
603 error = gfs2_glock_nq(ghs); /* parent */
604 if (error)
605 goto out_parent;
606
607 error = gfs2_glock_nq(ghs + 1); /* child */
608 if (error)
609 goto out_child;
610
611 error = -ENOENT;
612 if (ip->i_inode.i_nlink == 0)
613 goto out_rgrp;
614
615 error = gfs2_glock_nq(ghs + 2); /* rgrp */
616 if (error)
617 goto out_rgrp;
618
619 error = gfs2_unlink_ok(dip, &dentry->d_name, ip);
620 if (error)
621 goto out_gunlock;
622
623 if (ip->i_entries < 2) {
624 if (gfs2_consist_inode(ip))
625 gfs2_dinode_print(ip);
626 error = -EIO;
627 goto out_gunlock;
628 }
629 if (ip->i_entries > 2) {
630 error = -ENOTEMPTY;
631 goto out_gunlock;
632 }
633
634 error = gfs2_trans_begin(sdp, 2 * RES_DINODE + 3 * RES_LEAF + RES_RG_BIT, 0);
635 if (error)
636 goto out_gunlock;
637
638 error = gfs2_rmdiri(dip, &dentry->d_name, ip);
639
640 gfs2_trans_end(sdp);
641
642out_gunlock:
643 gfs2_glock_dq(ghs + 2);
644out_rgrp:
645 gfs2_holder_uninit(ghs + 2);
646 gfs2_glock_dq(ghs + 1);
647out_child:
648 gfs2_holder_uninit(ghs + 1);
649 gfs2_glock_dq(ghs);
650out_parent:
651 gfs2_holder_uninit(ghs);
652 gfs2_glock_dq_uninit(&ri_gh);
653 return error;
654}
655
656/**
657 * gfs2_mknod - Make a special file 575 * gfs2_mknod - Make a special file
658 * @dir: The directory in which the special file will reside 576 * @dir: The directory in which the special file will reside
659 * @dentry: The dentry of the special file 577 * @dentry: The dentry of the special file
@@ -930,25 +848,18 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
930 /* Remove the target file, if it exists */ 848 /* Remove the target file, if it exists */
931 849
932 if (nip) { 850 if (nip) {
933 if (S_ISDIR(nip->i_inode.i_mode)) 851 struct buffer_head *bh;
934 error = gfs2_rmdiri(ndip, &ndentry->d_name, nip); 852 error = gfs2_meta_inode_buffer(nip, &bh);
935 else {
936 error = gfs2_dir_del(ndip, &ndentry->d_name);
937 if (error)
938 goto out_end_trans;
939 error = gfs2_change_nlink(nip, -1);
940 }
941 if (error) 853 if (error)
942 goto out_end_trans; 854 goto out_end_trans;
855 error = gfs2_unlink_inode(ndip, ndentry, bh);
856 brelse(bh);
943 } 857 }
944 858
945 if (dir_rename) { 859 if (dir_rename) {
946 error = gfs2_change_nlink(ndip, +1); 860 error = gfs2_change_nlink(ndip, +1);
947 if (error) 861 if (error)
948 goto out_end_trans; 862 goto out_end_trans;
949 error = gfs2_change_nlink(odip, -1);
950 if (error)
951 goto out_end_trans;
952 863
953 error = gfs2_dir_mvino(ip, &gfs2_qdotdot, ndip, DT_DIR); 864 error = gfs2_dir_mvino(ip, &gfs2_qdotdot, ndip, DT_DIR);
954 if (error) 865 if (error)
@@ -964,7 +875,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
964 brelse(dibh); 875 brelse(dibh);
965 } 876 }
966 877
967 error = gfs2_dir_del(odip, &odentry->d_name); 878 error = gfs2_dir_del(odip, odentry);
968 if (error) 879 if (error)
969 goto out_end_trans; 880 goto out_end_trans;
970 881
@@ -1347,7 +1258,7 @@ const struct inode_operations gfs2_dir_iops = {
1347 .unlink = gfs2_unlink, 1258 .unlink = gfs2_unlink,
1348 .symlink = gfs2_symlink, 1259 .symlink = gfs2_symlink,
1349 .mkdir = gfs2_mkdir, 1260 .mkdir = gfs2_mkdir,
1350 .rmdir = gfs2_rmdir, 1261 .rmdir = gfs2_unlink,
1351 .mknod = gfs2_mknod, 1262 .mknod = gfs2_mknod,
1352 .rename = gfs2_rename, 1263 .rename = gfs2_rename,
1353 .permission = gfs2_permission, 1264 .permission = gfs2_permission,