On 2011-12-30, at 12:27 AM, Al Viro wrote: > One kinda-sorta solution (besides kicking cleancache out of tree) > would be to modify ->encode_fh() API - instead of dentry + connectable > pass it inode + NULL-or-parent-inode, with ->d_lock held by caller. And > demand it to be non-blocking, obviously... It would obviously break > ceph ->encode_fh(), since that sucker apparently wants the name of last > component anyway. OTOH, that's broken for reasons mentioned above. > OTTH, fhandle encoding is bloody close to user-visible ABI ;-/ Is it possible to always pass d_parent if this is available, rather than only if @connectable is passed? For network filesystems re-exporting NFS it is desirable to always be passed the parent directory. > diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c > index b05acb7..f8f7029 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,19 @@ 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 inode *inode = dentry->d_inode, *parent = NULL; > > + if (connectable && !S_ISDIR(inode->i_mode)) { > + spin_lock(&dentry->d_lock); > + parent = dentry->d_parent->d_inode; > + BUG_ON(!parent); > + } > 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); > + if (parent) > + spin_unlock(&dentry->d_lock); > > return error; > } Cheers, Andreas -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html