aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exportfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/exportfs')
-rw-r--r--fs/exportfs/expfs.c42
1 files changed, 25 insertions, 17 deletions
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index e9e175949a63..b05acb796135 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -43,24 +43,26 @@ find_acceptable_alias(struct dentry *result,
43 void *context) 43 void *context)
44{ 44{
45 struct dentry *dentry, *toput = NULL; 45 struct dentry *dentry, *toput = NULL;
46 struct inode *inode;
46 47
47 if (acceptable(context, result)) 48 if (acceptable(context, result))
48 return result; 49 return result;
49 50
50 spin_lock(&dcache_lock); 51 inode = result->d_inode;
51 list_for_each_entry(dentry, &result->d_inode->i_dentry, d_alias) { 52 spin_lock(&inode->i_lock);
52 dget_locked(dentry); 53 list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
53 spin_unlock(&dcache_lock); 54 dget(dentry);
55 spin_unlock(&inode->i_lock);
54 if (toput) 56 if (toput)
55 dput(toput); 57 dput(toput);
56 if (dentry != result && acceptable(context, dentry)) { 58 if (dentry != result && acceptable(context, dentry)) {
57 dput(result); 59 dput(result);
58 return dentry; 60 return dentry;
59 } 61 }
60 spin_lock(&dcache_lock); 62 spin_lock(&inode->i_lock);
61 toput = dentry; 63 toput = dentry;
62 } 64 }
63 spin_unlock(&dcache_lock); 65 spin_unlock(&inode->i_lock);
64 66
65 if (toput) 67 if (toput)
66 dput(toput); 68 dput(toput);
@@ -74,21 +76,20 @@ static struct dentry *
74find_disconnected_root(struct dentry *dentry) 76find_disconnected_root(struct dentry *dentry)
75{ 77{
76 dget(dentry); 78 dget(dentry);
77 spin_lock(&dentry->d_lock); 79 while (!IS_ROOT(dentry)) {
78 while (!IS_ROOT(dentry) && 80 struct dentry *parent = dget_parent(dentry);
79 (dentry->d_parent->d_flags & DCACHE_DISCONNECTED)) { 81
80 struct dentry *parent = dentry->d_parent; 82 if (!(parent->d_flags & DCACHE_DISCONNECTED)) {
81 dget(parent); 83 dput(parent);
82 spin_unlock(&dentry->d_lock); 84 break;
85 }
86
83 dput(dentry); 87 dput(dentry);
84 dentry = parent; 88 dentry = parent;
85 spin_lock(&dentry->d_lock);
86 } 89 }
87 spin_unlock(&dentry->d_lock);
88 return dentry; 90 return dentry;
89} 91}
90 92
91
92/* 93/*
93 * Make sure target_dir is fully connected to the dentry tree. 94 * Make sure target_dir is fully connected to the dentry tree.
94 * 95 *
@@ -319,9 +320,14 @@ static int export_encode_fh(struct dentry *dentry, struct fid *fid,
319 struct inode * inode = dentry->d_inode; 320 struct inode * inode = dentry->d_inode;
320 int len = *max_len; 321 int len = *max_len;
321 int type = FILEID_INO32_GEN; 322 int type = FILEID_INO32_GEN;
322 323
323 if (len < 2 || (connectable && len < 4)) 324 if (connectable && (len < 4)) {
325 *max_len = 4;
324 return 255; 326 return 255;
327 } else if (len < 2) {
328 *max_len = 2;
329 return 255;
330 }
325 331
326 len = 2; 332 len = 2;
327 fid->i32.ino = inode->i_ino; 333 fid->i32.ino = inode->i_ino;
@@ -368,6 +374,8 @@ struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
368 /* 374 /*
369 * Try to get any dentry for the given file handle from the filesystem. 375 * Try to get any dentry for the given file handle from the filesystem.
370 */ 376 */
377 if (!nop || !nop->fh_to_dentry)
378 return ERR_PTR(-ESTALE);
371 result = nop->fh_to_dentry(mnt->mnt_sb, fid, fh_len, fileid_type); 379 result = nop->fh_to_dentry(mnt->mnt_sb, fid, fh_len, fileid_type);
372 if (!result) 380 if (!result)
373 result = ERR_PTR(-ESTALE); 381 result = ERR_PTR(-ESTALE);