aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/ops_inode.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-03-20 12:30:04 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2006-03-20 12:30:04 -0500
commitc752666c17f870fa8ae9f16804dd457e9e6daaec (patch)
treec3c48383f386a24edbdf3c6292f25b587e6d9368 /fs/gfs2/ops_inode.c
parent419c93e0b6b9eef0bf26b8ad415f2a5bf4300119 (diff)
[GFS2] Fix bug in directory code and tidy up
Due to a typo, the dir leaf split operation was (for the first split in a directory) writing the new hash vaules at the wrong offset. This is now fixed. Also some other tidy ups are included: - We use GFS2's hash function for dentries (see ops_dentry.c) so that we don't have to keep recalculating the hash values. - A lot of common code is eliminated between the various directory lookup routines. - Better error checking on directory lookup (previously different routines checked for different errors) - The leaf split operation has a couple of redundant operations removed from it, so it should be faster. There is still further scope for further clean ups in the directory code, and readdir in particular could do with slimming down a bit. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/ops_inode.c')
-rw-r--r--fs/gfs2/ops_inode.c72
1 files changed, 35 insertions, 37 deletions
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index 7633a8584b0d..e8ab9d254b76 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -58,7 +58,6 @@ static int gfs2_create(struct inode *dir, struct dentry *dentry,
58 struct gfs2_holder ghs[2]; 58 struct gfs2_holder ghs[2];
59 struct inode *inode; 59 struct inode *inode;
60 int new = 1; 60 int new = 1;
61 int error;
62 61
63 gfs2_holder_init(dip->i_gl, 0, 0, ghs); 62 gfs2_holder_init(dip->i_gl, 0, 0, ghs);
64 63
@@ -78,14 +77,16 @@ static int gfs2_create(struct inode *dir, struct dentry *dentry,
78 return PTR_ERR(inode); 77 return PTR_ERR(inode);
79 } 78 }
80 79
81 error = gfs2_lookupi(dir, &dentry->d_name, 0, &inode); 80 inode = gfs2_lookupi(dir, &dentry->d_name, 0, nd);
82 if (!error) { 81 if (inode) {
83 new = 0; 82 if (!IS_ERR(inode)) {
84 gfs2_holder_uninit(ghs); 83 new = 0;
85 break; 84 gfs2_holder_uninit(ghs);
86 } else if (error != -ENOENT) { 85 break;
87 gfs2_holder_uninit(ghs); 86 } else {
88 return error; 87 gfs2_holder_uninit(ghs);
88 return PTR_ERR(inode);
89 }
89 } 90 }
90 } 91 }
91 92
@@ -110,17 +111,13 @@ static int gfs2_create(struct inode *dir, struct dentry *dentry,
110static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry, 111static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry,
111 struct nameidata *nd) 112 struct nameidata *nd)
112{ 113{
113 struct gfs2_inode *dip = dir->u.generic_ip;
114 struct gfs2_sbd *sdp = dip->i_sbd;
115 struct inode *inode = NULL; 114 struct inode *inode = NULL;
116 int error;
117 115
118 if (!sdp->sd_args.ar_localcaching) 116 dentry->d_op = &gfs2_dops;
119 dentry->d_op = &gfs2_dops;
120 117
121 error = gfs2_lookupi(dir, &dentry->d_name, 0, &inode); 118 inode = gfs2_lookupi(dir, &dentry->d_name, 0, nd);
122 if (error && error != -ENOENT) 119 if (inode && IS_ERR(inode))
123 return ERR_PTR(error); 120 return ERR_PTR(PTR_ERR(inode));
124 121
125 if (inode) 122 if (inode)
126 return d_splice_alias(inode, dentry); 123 return d_splice_alias(inode, dentry);
@@ -166,7 +163,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
166 if (error) 163 if (error)
167 goto out_gunlock; 164 goto out_gunlock;
168 165
169 error = gfs2_dir_search(dip, &dentry->d_name, NULL, NULL); 166 error = gfs2_dir_search(dir, &dentry->d_name, NULL, NULL);
170 switch (error) { 167 switch (error) {
171 case -ENOENT: 168 case -ENOENT:
172 break; 169 break;
@@ -192,10 +189,10 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
192 if (ip->i_di.di_nlink == (uint32_t)-1) 189 if (ip->i_di.di_nlink == (uint32_t)-1)
193 goto out_gunlock; 190 goto out_gunlock;
194 191
195 error = gfs2_diradd_alloc_required(dip, &dentry->d_name, 192 alloc_required = error = gfs2_diradd_alloc_required(dir, &dentry->d_name);
196 &alloc_required); 193 if (error < 0)
197 if (error)
198 goto out_gunlock; 194 goto out_gunlock;
195 error = 0;
199 196
200 if (alloc_required) { 197 if (alloc_required) {
201 struct gfs2_alloc *al = gfs2_alloc_get(dip); 198 struct gfs2_alloc *al = gfs2_alloc_get(dip);
@@ -228,7 +225,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
228 goto out_ipres; 225 goto out_ipres;
229 } 226 }
230 227
231 error = gfs2_dir_add(dip, &dentry->d_name, &ip->i_num, 228 error = gfs2_dir_add(dir, &dentry->d_name, &ip->i_num,
232 IF2DT(ip->i_di.di_mode)); 229 IF2DT(ip->i_di.di_mode));
233 if (error) 230 if (error)
234 goto out_end_trans; 231 goto out_end_trans;
@@ -419,24 +416,24 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode)
419 416
420 if (!gfs2_assert_withdraw(sdp, !error)) { 417 if (!gfs2_assert_withdraw(sdp, !error)) {
421 struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data; 418 struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data;
422 struct gfs2_dirent *dent; 419 struct gfs2_dirent *dent = (struct gfs2_dirent *)(di+1);
423 420 struct qstr str = { .name = ".", .len = 1 };
424 gfs2_dirent_alloc(ip, dibh, 1, &dent); 421 str.hash = gfs2_disk_hash(str.name, str.len);
425 422
423 gfs2_trans_add_bh(ip->i_gl, dibh, 1);
424 gfs2_qstr2dirent(&str, GFS2_DIRENT_SIZE(str.len), dent);
426 dent->de_inum = di->di_num; /* already GFS2 endian */ 425 dent->de_inum = di->di_num; /* already GFS2 endian */
427 dent->de_hash = gfs2_disk_hash(".", 1);
428 dent->de_hash = cpu_to_be32(dent->de_hash);
429 dent->de_type = DT_DIR; 426 dent->de_type = DT_DIR;
430 memcpy((char *) (dent + 1), ".", 1);
431 di->di_entries = cpu_to_be32(1); 427 di->di_entries = cpu_to_be32(1);
432 428
433 gfs2_dirent_alloc(ip, dibh, 2, &dent); 429 str.name = "..";
430 str.len = 2;
431 str.hash = gfs2_disk_hash(str.name, str.len);
432 dent = (struct gfs2_dirent *)((char*)dent + GFS2_DIRENT_SIZE(1));
433 gfs2_qstr2dirent(&str, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent);
434 434
435 gfs2_inum_out(&dip->i_num, (char *) &dent->de_inum); 435 gfs2_inum_out(&dip->i_num, (char *) &dent->de_inum);
436 dent->de_hash = gfs2_disk_hash("..", 2);
437 dent->de_hash = cpu_to_be32(dent->de_hash);
438 dent->de_type = DT_DIR; 436 dent->de_type = DT_DIR;
439 memcpy((char *) (dent + 1), "..", 2);
440 437
441 gfs2_dinode_out(&ip->i_di, (char *)di); 438 gfs2_dinode_out(&ip->i_di, (char *)di);
442 439
@@ -687,7 +684,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
687 if (error) 684 if (error)
688 goto out_gunlock; 685 goto out_gunlock;
689 686
690 error = gfs2_dir_search(ndip, &ndentry->d_name, NULL, NULL); 687 error = gfs2_dir_search(ndir, &ndentry->d_name, NULL, NULL);
691 switch (error) { 688 switch (error) {
692 case -ENOENT: 689 case -ENOENT:
693 error = 0; 690 error = 0;
@@ -723,10 +720,10 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
723 goto out_gunlock; 720 goto out_gunlock;
724 } 721 }
725 722
726 error = gfs2_diradd_alloc_required(ndip, &ndentry->d_name, 723 alloc_required = error = gfs2_diradd_alloc_required(ndir, &ndentry->d_name);
727 &alloc_required); 724 if (error < 0)
728 if (error)
729 goto out_gunlock; 725 goto out_gunlock;
726 error = 0;
730 727
731 if (alloc_required) { 728 if (alloc_required) {
732 struct gfs2_alloc *al = gfs2_alloc_get(ndip); 729 struct gfs2_alloc *al = gfs2_alloc_get(ndip);
@@ -777,6 +774,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
777 struct qstr name; 774 struct qstr name;
778 name.len = 2; 775 name.len = 2;
779 name.name = ".."; 776 name.name = "..";
777 name.hash = gfs2_disk_hash(name.name, name.len);
780 778
781 error = gfs2_change_nlink(ndip, +1); 779 error = gfs2_change_nlink(ndip, +1);
782 if (error) 780 if (error)
@@ -803,7 +801,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
803 if (error) 801 if (error)
804 goto out_end_trans; 802 goto out_end_trans;
805 803
806 error = gfs2_dir_add(ndip, &ndentry->d_name, &ip->i_num, 804 error = gfs2_dir_add(ndir, &ndentry->d_name, &ip->i_num,
807 IF2DT(ip->i_di.di_mode)); 805 IF2DT(ip->i_di.di_mode));
808 if (error) 806 if (error)
809 goto out_end_trans; 807 goto out_end_trans;