summaryrefslogtreecommitdiff
path: root/fs/exportfs/expfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/exportfs/expfs.c')
-rw-r--r--fs/exportfs/expfs.c33
1 files changed, 19 insertions, 14 deletions
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index b05acb796135..b0201ca6e9c6 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -304,24 +304,23 @@ out:
/**
* export_encode_fh - default export_operations->encode_fh function
- * @dentry: the dentry to encode
+ * @inode: the object to encode
* @fh: where to store the file handle fragment
* @max_len: maximum length to store there
- * @connectable: whether to store parent information
+ * @parent: parent directory inode, if wanted
*
* This default encode_fh function assumes that the 32 inode number
* is suitable for locating an inode, and that the generation number
* can be used to check that it is still valid. It places them in the
* filehandle fragment where export_decode_fh expects to find them.
*/
-static int export_encode_fh(struct dentry *dentry, struct fid *fid,
- int *max_len, int connectable)
+static int export_encode_fh(struct inode *inode, struct fid *fid,
+ int *max_len, struct inode *parent)
{
- struct inode * inode = dentry->d_inode;
int len = *max_len;
int type = FILEID_INO32_GEN;
- if (connectable && (len < 4)) {
+ if (parent && (len < 4)) {
*max_len = 4;
return 255;
} else if (len < 2) {
@@ -332,14 +331,9 @@ static int export_encode_fh(struct dentry *dentry, struct fid *fid,
len = 2;
fid->i32.ino = inode->i_ino;
fid->i32.gen = inode->i_generation;
- if (connectable && !S_ISDIR(inode->i_mode)) {
- struct inode *parent;
-
- spin_lock(&dentry->d_lock);
- parent = dentry->d_parent->d_inode;
+ if (parent) {
fid->i32.parent_ino = parent->i_ino;
fid->i32.parent_gen = parent->i_generation;
- spin_unlock(&dentry->d_lock);
len = 4;
type = FILEID_INO32_GEN_PARENT;
}
@@ -352,11 +346,22 @@ int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len,
{
const struct export_operations *nop = dentry->d_sb->s_export_op;
int error;
+ struct dentry *p = NULL;
+ struct inode *inode = dentry->d_inode, *parent = NULL;
+ if (connectable && !S_ISDIR(inode->i_mode)) {
+ p = dget_parent(dentry);
+ /*
+ * note that while p might've ceased to be our parent already,
+ * it's still pinned by and still positive.
+ */
+ parent = p->d_inode;
+ }
if (nop->encode_fh)
- error = nop->encode_fh(dentry, fid->raw, max_len, connectable);
+ error = nop->encode_fh(inode, fid->raw, max_len, parent);
else
- error = export_encode_fh(dentry, fid, max_len, connectable);
+ error = export_encode_fh(inode, fid, max_len, parent);
+ dput(p);
return error;
}