On Wed, Dec 03, 2008 at 06:30:44PM +0000, David Howells wrote: > Update the exportfs documentation and comments to fit the code, and add an > extra FID type to be used for error indication (FILEID_ERROR). > > The following other code changes have been made: > > (*) The encode_fh() op and exportfs_encode_fh() return enum fid_type rather > than int. > > (*) The exportfs_encode_fh() function has it's acceptable() function pointer > typedef'd. > > (*) The fh_to_dentry() and fh_to_parent() ops and exportfs_decode_fh() take > enum fid_type rather than int. > > (*) The generic_fh_to_dentry() and generic_fh_to_parent() functions now take > enum fid_type rather than int. Their get_inode() function pointer has > been typedef'd. > > (*) Returns from encode_fh() implementations of 255 are changed to > FILEID_ERROR. > > (*) FAT has had its fh type #defined (FAT_FILEID). > > (*) FUSE has had its fh types #defined (FUSE_FILEID, FUSE_FILEID_PARENT). > > (*) ISOFS has had its fh types #defined (ISOFS_FILEID, ISOFS_FILEID_PARENT). > > (*) OCFS2 has had its fh types #defined (OCFS2_FILEID, OCFS2_FILEID_PARENT). Could we get separate patches for these? --b. > > Signed-off-by: David Howells <dhowells@xxxxxxxxxx> > --- > > Documentation/filesystems/Exporting | 400 +++++++++++++++++++++++------------ > fs/efs/efs.h | 5 > fs/efs/namei.c | 4 > fs/exportfs/expfs.c | 97 ++++++-- > fs/ext2/super.c | 4 > fs/ext3/super.c | 4 > fs/ext4/super.c | 4 > fs/fat/inode.c | 12 + > fs/fuse/inode.c | 18 +- > fs/gfs2/ops_export.c | 14 + > fs/isofs/export.c | 19 +- > fs/jffs2/super.c | 4 > fs/jfs/jfs_inode.h | 5 > fs/jfs/namei.c | 4 > fs/libfs.c | 10 - > fs/ntfs/namei.c | 4 > fs/ocfs2/export.c | 21 +- > fs/reiserfs/inode.c | 10 - > fs/udf/namei.c | 14 + > fs/xfs/linux-2.6/xfs_export.c | 12 + > include/linux/exportfs.h | 117 +++++++--- > include/linux/reiserfs_fs.h | 9 - > mm/shmem.c | 6 - > 23 files changed, 512 insertions(+), 285 deletions(-) > > > diff --git a/Documentation/filesystems/Exporting b/Documentation/filesystems/Exporting > index 87019d2..5d9d769 100644 > --- a/Documentation/filesystems/Exporting > +++ b/Documentation/filesystems/Exporting > @@ -1,147 +1,273 @@ > + ============================= > + MAKING FILESYSTEMS EXPORTABLE > + ============================= > > -Making Filesystems Exportable > -============================= > - > -Overview > --------- > - > -All filesystem operations require a dentry (or two) as a starting > -point. Local applications have a reference-counted hold on suitable > -dentries via open file descriptors or cwd/root. However remote > -applications that access a filesystem via a remote filesystem protocol > -such as NFS may not be able to hold such a reference, and so need a > -different way to refer to a particular dentry. As the alternative > -form of reference needs to be stable across renames, truncates, and > -server-reboot (among other things, though these tend to be the most > -problematic), there is no simple answer like 'filename'. > - > -The mechanism discussed here allows each filesystem implementation to > -specify how to generate an opaque (outside of the filesystem) byte > -string for any dentry, and how to find an appropriate dentry for any > -given opaque byte string. > -This byte string will be called a "filehandle fragment" as it > -corresponds to part of an NFS filehandle. > - > -A filesystem which supports the mapping between filehandle fragments > -and dentries will be termed "exportable". > - > - > - > -Dcache Issues > -------------- > - > -The dcache normally contains a proper prefix of any given filesystem > -tree. This means that if any filesystem object is in the dcache, then > -all of the ancestors of that filesystem object are also in the dcache. > -As normal access is by filename this prefix is created naturally and > -maintained easily (by each object maintaining a reference count on > -its parent). > - > -However when objects are included into the dcache by interpreting a > -filehandle fragment, there is no automatic creation of a path prefix > -for the object. This leads to two related but distinct features of > -the dcache that are not needed for normal filesystem access. > - > -1/ The dcache must sometimes contain objects that are not part of the > - proper prefix. i.e that are not connected to the root. > -2/ The dcache must be prepared for a newly found (via ->lookup) directory > - to already have a (non-connected) dentry, and must be able to move > - that dentry into place (based on the parent and name in the > - ->lookup). This is particularly needed for directories as > - it is a dcache invariant that directories only have one dentry. > - > -To implement these features, the dcache has: > - > -a/ A dentry flag DCACHE_DISCONNECTED which is set on > - any dentry that might not be part of the proper prefix. > - This is set when anonymous dentries are created, and cleared when a > - dentry is noticed to be a child of a dentry which is in the proper > - prefix. > - > -b/ A per-superblock list "s_anon" of dentries which are the roots of > - subtrees that are not in the proper prefix. These dentries, as > - well as the proper prefix, need to be released at unmount time. As > - these dentries will not be hashed, they are linked together on the > - d_hash list_head. > - > -c/ Helper routines to allocate anonymous dentries, and to help attach > - loose directory dentries at lookup time. They are: > - d_alloc_anon(inode) will return a dentry for the given inode. > - If the inode already has a dentry, one of those is returned. > - If it doesn't, a new anonymous (IS_ROOT and > - DCACHE_DISCONNECTED) dentry is allocated and attached. > - In the case of a directory, care is taken that only one dentry > - can ever be attached. > - d_splice_alias(inode, dentry) will make sure that there is a > - dentry with the same name and parent as the given dentry, and > - which refers to the given inode. > - If the inode is a directory and already has a dentry, then that > - dentry is d_moved over the given dentry. > - If the passed dentry gets attached, care is taken that this is > - mutually exclusive to a d_alloc_anon operation. > - If the passed dentry is used, NULL is returned, else the used > - dentry is returned. This corresponds to the calling pattern of > - ->lookup. > - > - > -Filesystem Issues > ------------------ > +Contents: > + > + (*) Overview. > + > + (*) Dealing with the directory entry cache. > + > + (*) Making a filesystem exportable. > + > + (*) Filehandle fragment format. > + > + (*) Filehandle export operations. > + > + > +======== > +OVERVIEW > +======== > + > +All filesystem operations require a dentry (or two) as a starting point. Local > +applications have a reference-counted hold on suitable dentries via open file > +descriptors, the current working directory and the current root directory. > +Remote applications that access a filesystem via a remote filesystem protocol > +such as NFS, however, may not be able to hold such a reference, and so need a > +different way to refer to a particular dentry. As the alternative form of > +reference needs to be persistent across renames, truncates, and server reboots > +(among other events, though these tend to be the most problematic), there is no > +simple answer like 'filename'. > + > +The mechanism discussed here allows each filesystem implementation to specify > +how to generate an opaque (outside of the filesystem) byte string for any > +dentry, and how to find an appropriate dentry for any given opaque byte string. > + > +This byte string will be called a "filehandle fragment" as it corresponds to > +part of an NFS filehandle. > + > +A filesystem which supports the mapping between filehandle fragments and > +dentries will be termed "exportable". > + > + > +====================================== > +DEALING WITH THE DIRECTORY ENTRY CACHE > +====================================== > + > +Each superblock has a tree of directory entries (dentries) that is rooted at > +its s_root pointer. For most filesystems, every dentry it currently has cached > +in RAM is connected to this tree, meaning that all the ancestors of most files > +are fully represented in the directory entry cache (dcache). > + > +As the normal method of accessing files is by filename, the superblock root > +tree builds up in a natural manner, and is maintained simply by each object > +having a reference count on its parent. The pathwalk algorithm works by > +walking from the root and out along the branches to the desired object. > + > +However, when an object is brought into the dcache by interpreting a filehandle > +fragment, the entries for the directories that represent that object's ancestry > +are not automatically all brought into the cache as well. This leads to two > +related but distinct issues in the dcache that are not ordinarily seen: > + > + (1) Sometimes the dcache for a superblock must contain objects that are not > + connected to that superblock's root tree. > + > + (2) The dcache must be able to handle a lookup() operation that results in a > + dentry that already exists. In such a case, the already extant dentry > + must be used instead of the candidate upon which the lookup was performed. > + > + Furthermore, the lookup procedure must be able to handle unconnected > + dentries so found by installing them in the dentry tree under the parent > + specified directory. > + > + This is particularly necessary for directories as it is a requirement of > + the dcache that directories are represented by a single dentry and don't > + have aliases. > + > +To manage the above, the dcache has the following features: > + > + (A) A dentry flag DCACHE_DISCONNECTED which is set on any dentry that might > + not be connected to the superblock root. This is set when anonymous > + dentries are created, and cleared when a dentry is noticed to be a child > + of a dentry which is in the proper prefix. > + > + (B) A per-superblock list of dentries (s_anon) which are the roots of subtrees > + that are not connected to the superblock root. These dentries, as well as > + the superblock's rooted tree, need to be released at unmount time. > + > + Note that as these dentries are unhashed, the s_anon list is linked > + together using the d_hash list_head in the dentry struct. > + > + (C) Helper routines to allocate anonymous dentries, and to help attach loose > + directory dentries at lookup time. They are: > + > + (*) Find or allocate a dentry for a given inode. > + > + struct dentry *d_obtain_alias(struct inode *inode); > + > + This will return a dentry for the given inode. If the inode already > + has a dentry, one of those is returned. If it doesn't, a new > + anonymous (IS_ROOT() and DCACHE_DISCONNECTED) dentry is allocated and > + attached. In the case of a directory, care is taken that only one > + dentry can ever be attached. > + > + (*) Splice a disconnected dentry into the tree if one exists. > + > + struct dentry *d_splice_alias(struct inode *inode, > + struct dentry *dentry); > + > + This will make sure that there is a dentry with the same name and > + parent as the given dentry, and which refers to the given inode. > + > + If the inode is a directory and already has a dentry, then that dentry > + is d_move()'d over the given dentry. If the passed dentry gets > + attached, care is taken that this is mutually exclusive to a > + d_obtain_alias() operation. If the passed dentry is used, NULL is > + returned, else the used dentry is returned. This corresponds to the > + calling pattern of the lookup procedure. > + > + > +============================== > +MAKING A FILESYSTEM EXPORTABLE > +============================== > > For a filesystem to be exportable it must: > - > - 1/ provide the filehandle fragment routines described below. > - 2/ make sure that d_splice_alias is used rather than d_add > - when ->lookup finds an inode for a given parent and name. > - Typically the ->lookup routine will end with a: > > + (1) Provide the filehandle export operations described below. > + > + (2) Make sure that d_splice_alias() is used rather than d_add() when its > + lookup() operation finds an inode for a given parent and name. Typically > + the lookup() routine will end with a: > + > + { > + ... > return d_splice_alias(inode, dentry); > } > > > +========================== > +FILEHANDLE FRAGMENT FORMAT > +========================== > + > +A filehandle fragment consists of an array of 1 or more 32-bit words. The > +contents and the layout of the data in the array are entirely at the whim of > +the filesystem that generated it. > + > +The filehandle fragment produced also has a 'type' associated with it. This > +is a number between 0 and 254. 0 is a special reserved value (FILEID_ROOT) > +that encode_fh() may not produce. The remaining values in that range can be > +chosen at will, though there are possible symbols in the fid_type enum that can > +be used if desired. Beware, though, these may be decoded by protocol decoding > +programs, such as wireshark, so using a predefined type may confuse people if > +the corresponding format is not also adhered to (see the fid struct). > > - A file system implementation declares that instances of the filesystem > -are exportable by setting the s_export_op field in the struct > -super_block. This field must point to a "struct export_operations" > -struct which has the following members: > - > - encode_fh (optional) > - Takes a dentry and creates a filehandle fragment which can later be used > - to find or create a dentry for the same object. The default > - implementation creates a filehandle fragment that encodes a 32bit inode > - and generation number for the inode encoded, and if necessary the > - same information for the parent. > - > - fh_to_dentry (mandatory) > - Given a filehandle fragment, this should find the implied object and > - create a dentry for it (possibly with d_alloc_anon). > - > - fh_to_parent (optional but strongly recommended) > - Given a filehandle fragment, this should find the parent of the > - implied object and create a dentry for it (possibly with d_alloc_anon). > - May fail if the filehandle fragment is too small. > - > - get_parent (optional but strongly recommended) > - When given a dentry for a directory, this should return a dentry for > - the parent. Quite possibly the parent dentry will have been allocated > - by d_alloc_anon. The default get_parent function just returns an error > - so any filehandle lookup that requires finding a parent will fail. > - ->lookup("..") is *not* used as a default as it can leave ".." entries > - in the dcache which are too messy to work with. > - > - get_name (optional) > - When given a parent dentry and a child dentry, this should find a name > - in the directory identified by the parent dentry, which leads to the > - object identified by the child dentry. If no get_name function is > - supplied, a default implementation is provided which uses vfs_readdir > - to find potential names, and matches inode numbers to find the correct > - match. > - > - > -A filehandle fragment consists of an array of 1 or more 4byte words, > -together with a one byte "type". > -The decode_fh routine should not depend on the stated size that is > -passed to it. This size may be larger than the original filehandle > -generated by encode_fh, in which case it will have been padded with > -nuls. Rather, the encode_fh routine should choose a "type" which > -indicates the decode_fh how much of the filehandle is valid, and how > +The fh_to_dentry() and fh_to_parent() routines should not depend on the stated > +size that is passed to them. This size may be larger than the original > +filehandle generated by encode_fh(), in which case it will have been padded > +with NULs. Rather, the encode_fh() routine should choose a "type" which > +indicates the fh_to_*() operations how much of the filehandle is valid, and how > it should be interpreted. > + > + > +============================ > +FILEHANDLE EXPORT OPERATIONS > +============================ > + > +A filesystem implementation declares that instances of the filesystem are > +exportable by setting the s_export_op field in the super_block struct. This > +field must point to an export_operations struct which has the following members > +filled in: > + > + (*) enum fid_type (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len, > + int connectable); > + > + This operation is used to generate a filehandle fragment that can later be > + used to find or create a dentry for the same filesystem object. It is > + optional and there's a default encoder. > + > + The fragment is written into the supplied buffer - fh - which can hold up > + to *max_len lots of 4-byte words. The fragment generated should represent > + the given dentry, and if connectable is set, the parent of the given > + dentry too. > + > + If successful, this operation should return a value that represents to the > + decoder operations the format of the opaque fragment produced and it > + should set *max_len to indicate the amount of data it stored in the buffer > + in units of 32-bit words. > + > + The caller is required to save the type value for presentation to the > + decoder operations. The type value is arbitrary, but must be between 1 > + and 254. There are some predefined types in the fid_type enum that can be > + selected, but use of these is not mandatory. > + > + Upon failure, a value of FILEID_ERROR should be returned. > + > + The default encoder uses the i_ino and i_generation numbers from the > + inode, both masked down to 32-bits. It also adds both values from the > + parent inode if connectable. > + > + (*) struct dentry *(*fh_to_dentry)(struct super_block *sb, struct fid *fid, > + int fh_len, enum fid_type fh_type); > + > + This operation is used to look up a file, given the filehandle fragment > + that was generated by encode_fh(). The file, if it exists, will be one of > + the set available through the specified superblock. This operation is > + mandatory. > + > + The filehandle fragment is in the buffer specified by fid and is of up to > + fh_len 32-bit words and is of type fh_type as indicated by encode_fh(). > + Note that there may be more data than expected in the buffer as the data > + may have been padded out by the caller. fh_type must be used to deal with > + this. > + > + If successful, this operation should return a pointer to a dcache entry > + representing one of the aliases to the file. This may be used by the > + caller to query other aliases of the same file to find one it prefers. > + > + Note that this operation is not required to produce an dentry that is > + connected to the root of the superblock. It is permitted to produce an > + anonymous dentry, as might happen if encode_fh() was given connectable as > + false. > + > + On failure, a negative error code should be produced to indicate the > + reason. A NULL pointer must not be returned. > + > + (*) struct dentry *(*fh_to_parent)(struct super_block *sb, struct fid *fid, > + int fh_len, enum fid_type fh_type); > + > + This is very similar to fh_to_dentry(), the difference being that it > + attempts to retrieve the parent of the file to which the filehandle > + fragment corresponds, rather than the file itself. This operation is > + optional, but is strongly recommended. > + > + This may fail if the filehandle does not contain information on the > + original file's parentage. It also need not produce a fully connected > + dentry. > + > + (*) struct dentry *(*get_parent)(struct dentry *child); > + > + This operation should return a dentry to represent the parent directory of > + the specified dentry (which should itself be a directory). This operation > + is optional, but strongly recommended. > + > + An anonymous, unconnected dentry can be returned as the parent if so > + desired. This may be allocated with d_obtain_alias() or suchlike. > + > + On success, the parent dentry should be returned. On failure, a negative > + error code should be returned. > + > + The default operation just returns an error, thus making any filehandle > + lookup that requires finding the parent fail. The default operation does > + not try to use 'lookup("..")' as that could leave ".." entries in the > + dcache. > + > + (*) int (*get_name)(struct dentry *parent, char *name, struct dentry *child); > + > + This operation is provided to determine the name of the directory entry in > + the parent directory that points to the child object. This operation is > + optional. > + > + On success, the NUL-terminated name of the directory entry should be > + written into the name buffer, and zero should be returned. The caller > + must guarantee that the buffer is at least NAME_MAX + 1 in size. > + > + On failure, a negative error code should be returned. > + > + The default operation is available that uses vfs_readdir() to find > + potential names and match inode numbers to select the correct entry. > + > +This interface can be included in the code by: > + > + #include <linux/exportfs.h> > + > +and making the user dependent on CONFIG_EXPORTFS. > diff --git a/fs/efs/efs.h b/fs/efs/efs.h > index d8305b5..db5e1c2 100644 > --- a/fs/efs/efs.h > +++ b/fs/efs/efs.h > @@ -8,6 +8,7 @@ > #define _EFS_EFS_H_ > > #include <linux/fs.h> > +#include <linux/exportfs.h> > #include <asm/uaccess.h> > > #define EFS_VERSION "1.0a" > @@ -131,9 +132,9 @@ extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int); > > extern struct dentry *efs_lookup(struct inode *, struct dentry *, struct nameidata *); > extern struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type); > + int fh_len, enum fid_type fh_type); > extern struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type); > + int fh_len, enum fid_type fh_type); > extern struct dentry *efs_get_parent(struct dentry *); > extern int efs_bmap(struct inode *, int); > > diff --git a/fs/efs/namei.c b/fs/efs/namei.c > index c3fb5f9..6b9c118 100644 > --- a/fs/efs/namei.c > +++ b/fs/efs/namei.c > @@ -97,14 +97,14 @@ static struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino, > } > > struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type) > + int fh_len, enum fid_type fh_type) > { > return generic_fh_to_dentry(sb, fid, fh_len, fh_type, > efs_nfs_get_inode); > } > > struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type) > + int fh_len, enum fid_type fh_type) > { > return generic_fh_to_parent(sb, fid, fh_len, fh_type, > efs_nfs_get_inode); > diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c > index ec1fb91..46039b4 100644 > --- a/fs/exportfs/expfs.c > +++ b/fs/exportfs/expfs.c > @@ -35,12 +35,12 @@ static int exportfs_get_name(struct vfsmount *mnt, struct dentry *dir, > } > > /* > - * Check if the dentry or any of it's aliases is acceptable. > + * Check if the dentry or any of it's aliases are acceptable. > */ > static struct dentry * > find_acceptable_alias(struct dentry *result, > - int (*acceptable)(void *context, struct dentry *dentry), > - void *context) > + exportfs_acceptable_t acceptable, > + void *context) > { > struct dentry *dentry, *toput = NULL; > > @@ -303,25 +303,25 @@ out: > > /** > * export_encode_fh - default export_operations->encode_fh function > - * @dentry: the dentry to encode > - * @fh: where to store the file handle fragment > - * @max_len: maximum length to store there > - * @connectable: whether to store parent information > + * @dentry: The dentry to encode > + * @fid: Where to store the file handle fragment > + * @max_len: Maximum length to store there in 32-bit words > + * @connectable: Whether to store parent information > * > - * 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. > + * 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 enum fid_type export_encode_fh(struct dentry *dentry, struct fid *fid, > + int *max_len, int connectable) > { > struct inode * inode = dentry->d_inode; > int len = *max_len; > - int type = FILEID_INO32_GEN; > - > + enum fid_type type = FILEID_INO32_GEN; > + > if (len < 2 || (connectable && len < 4)) > - return 255; > + return FILEID_ERROR; > > len = 2; > fid->i32.ino = inode->i_ino; > @@ -341,24 +341,71 @@ static int export_encode_fh(struct dentry *dentry, struct fid *fid, > return type; > } > > -int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len, > - int connectable) > +/** > + * exportfs_encode_fh - Encode a dentry to a partial persistent file handle > + * @dentry: The dentry to encode > + * @fid: Where to store the file handle fragment > + * @max_len: Maximum length to store there in 32-bit words > + * @connectable: Whether to store parent information > + * > + * This function is used to get a partial persistent file handle to represent a > + * file object as referred to by the given dentry. The caller may also request > + * that parentage information be noted in the file handle produced. > + * > + * The fid pointer should point to a buffer of *max_len size, where the maximum > + * length is given in 32-bit words, _not_ bytes. The contents of the returned > + * file handle may or may not reflect the layout of the fid structure. That is > + * totally up to the filesystem being queried. > + * > + * On return, the file handle type will be returned, or FILEID_ERROR if the > + * filesystem was unable to represent the file. The caller is responsible for > + * saving the type so that it can be passed to exportfs_decode_fh(). > + * > + * If successful, *max_len will have been updated to specify the amount of > + * buffer actually used. > + */ > +enum fid_type exportfs_encode_fh(struct dentry *dentry, struct fid *fid, > + int *max_len, int connectable) > { > const struct export_operations *nop = dentry->d_sb->s_export_op; > - int error; > > if (nop->encode_fh) > - error = nop->encode_fh(dentry, fid->raw, max_len, connectable); > + return nop->encode_fh(dentry, fid->raw, max_len, connectable); > else > - error = export_encode_fh(dentry, fid, max_len, connectable); > - > - return error; > + return export_encode_fh(dentry, fid, max_len, connectable); > } > EXPORT_SYMBOL_GPL(exportfs_encode_fh); > > +/** > + * exportfs_decode_fh - Decode a partial persistent file handle to a dentry > + * @mnt: The mountpoint with which the dentry should be associated > + * @fid: The partial file handle > + * @fh_len: The length of the partial file handle > + * @fileid_type: The type of partial file handle > + * @acceptable: A filter routine to pick amongst the aliases for an inode > + * @context: Context information for the acceptability filter > + * > + * This function function is used to turn a partial persistent file handle back > + * into the dentry it represents. The caller must indicate the set of dentries > + * from which the target is to be selected by the VFS mountpoint supplied. > + * > + * The partial file handle is in the buffer pointed to by the fid pointer, and > + * is fh_len 32-bit words in length. The fileid_type as returned by the encode > + * routine must also be presented by the caller. > + * > + * If a suitable inode is found, its list of aliases will be passed to the > + * acceptability function to select a suitable one. The context information > + * supplied will be passed to the acceptability filter to aid in selection. > + * > + * If successful, a pointer to a suitable dentry will be returned. Note that > + * dentry returned may not be connected to any of the superblock's roots. > + * > + * If unsuccessful, a negative error code will be returned. > + */ > struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid, > - int fh_len, int fileid_type, > - int (*acceptable)(void *, struct dentry *), void *context) > + int fh_len, enum fid_type fileid_type, > + exportfs_acceptable_t acceptable, > + void *context) > { > const struct export_operations *nop = mnt->mnt_sb->s_export_op; > struct dentry *result, *alias; > diff --git a/fs/ext2/super.c b/fs/ext2/super.c > index 647cd88..a3ef820 100644 > --- a/fs/ext2/super.c > +++ b/fs/ext2/super.c > @@ -340,14 +340,14 @@ static struct inode *ext2_nfs_get_inode(struct super_block *sb, > } > > static struct dentry *ext2_fh_to_dentry(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type) > + int fh_len, enum fid_type fh_type) > { > return generic_fh_to_dentry(sb, fid, fh_len, fh_type, > ext2_nfs_get_inode); > } > > static struct dentry *ext2_fh_to_parent(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type) > + int fh_len, enum fid_type fh_type) > { > return generic_fh_to_parent(sb, fid, fh_len, fh_type, > ext2_nfs_get_inode); > diff --git a/fs/ext3/super.c b/fs/ext3/super.c > index f6c94f2..b549bbd 100644 > --- a/fs/ext3/super.c > +++ b/fs/ext3/super.c > @@ -669,14 +669,14 @@ static struct inode *ext3_nfs_get_inode(struct super_block *sb, > } > > static struct dentry *ext3_fh_to_dentry(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type) > + int fh_len, enum fid_type fh_type) > { > return generic_fh_to_dentry(sb, fid, fh_len, fh_type, > ext3_nfs_get_inode); > } > > static struct dentry *ext3_fh_to_parent(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type) > + int fh_len, enum fid_type fh_type) > { > return generic_fh_to_parent(sb, fid, fh_len, fh_type, > ext3_nfs_get_inode); > diff --git a/fs/ext4/super.c b/fs/ext4/super.c > index e4a241c..30e142b 100644 > --- a/fs/ext4/super.c > +++ b/fs/ext4/super.c > @@ -759,14 +759,14 @@ static struct inode *ext4_nfs_get_inode(struct super_block *sb, > } > > static struct dentry *ext4_fh_to_dentry(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type) > + int fh_len, enum fid_type fh_type) > { > return generic_fh_to_dentry(sb, fid, fh_len, fh_type, > ext4_nfs_get_inode); > } > > static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type) > + int fh_len, enum fid_type fh_type) > { > return generic_fh_to_parent(sb, fid, fh_len, fh_type, > ext4_nfs_get_inode); > diff --git a/fs/fat/inode.c b/fs/fat/inode.c > index cac84f2..b0bb1f4 100644 > --- a/fs/fat/inode.c > +++ b/fs/fat/inode.c > @@ -649,14 +649,16 @@ static const struct super_operations fat_sops = { > * of i_logstart is used to store the directory entry offset. > */ > > +#define FAT_FILEID 3 > + > static struct dentry *fat_fh_to_dentry(struct super_block *sb, > - struct fid *fid, int fh_len, int fh_type) > + struct fid *fid, int fh_len, enum fid_type fh_type) > { > struct inode *inode = NULL; > struct dentry *result; > u32 *fh = fid->raw; > > - if (fh_len < 5 || fh_type != 3) > + if (fh_len < 5 || fh_type != FAT_FILEID) > return ERR_PTR(-ESTALE); > > inode = ilookup(sb, fh[0]); > @@ -704,7 +706,7 @@ static struct dentry *fat_fh_to_dentry(struct super_block *sb, > return result; > } > > -static int > +static enum fid_type > fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable) > { > int len = *lenp; > @@ -712,7 +714,7 @@ fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable) > u32 ipos_h, ipos_m, ipos_l; > > if (len < 5) > - return 255; /* no room */ > + return FILEID_ERROR; /* no room */ > > ipos_h = MSDOS_I(inode)->i_pos >> 8; > ipos_m = (MSDOS_I(inode)->i_pos & 0xf0) << 24; > @@ -725,7 +727,7 @@ fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable) > spin_lock(&de->d_lock); > fh[4] = ipos_l | MSDOS_I(de->d_parent->d_inode)->i_logstart; > spin_unlock(&de->d_lock); > - return 3; > + return FAT_FILEID; > } > > static struct dentry *fat_get_parent(struct dentry *child) > diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c > index 0eb8990..3e1da5c 100644 > --- a/fs/fuse/inode.c > +++ b/fs/fuse/inode.c > @@ -610,8 +610,11 @@ static struct dentry *fuse_get_dentry(struct super_block *sb, > return ERR_PTR(err); > } > > -static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len, > - int connectable) > +#define FUSE_FILEID 0x81 > +#define FUSE_FILEID_PARENT 0x82 > + > +static enum fid_type fuse_encode_fh(struct dentry *dentry, u32 *fh, > + int *max_len, int connectable) > { > struct inode *inode = dentry->d_inode; > bool encode_parent = connectable && !S_ISDIR(inode->i_mode); > @@ -620,7 +623,7 @@ static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len, > u32 generation; > > if (*max_len < len) > - return 255; > + return FILEID_ERROR; > > nodeid = get_fuse_inode(inode)->nodeid; > generation = inode->i_generation; > @@ -644,15 +647,16 @@ static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len, > } > > *max_len = len; > - return encode_parent ? 0x82 : 0x81; > + return encode_parent ? FUSE_FILEID_PARENT : FUSE_FILEID; > } > > static struct dentry *fuse_fh_to_dentry(struct super_block *sb, > - struct fid *fid, int fh_len, int fh_type) > + struct fid *fid, int fh_len, enum fid_type fh_type) > { > struct fuse_inode_handle handle; > > - if ((fh_type != 0x81 && fh_type != 0x82) || fh_len < 3) > + if ((fh_type != FUSE_FILEID && fh_type != FUSE_FILEID_PARENT) || > + fh_len < 3) > return ERR_PTR(-ESTALE); > > handle.nodeid = (u64) fid->raw[0] << 32; > @@ -662,7 +666,7 @@ static struct dentry *fuse_fh_to_dentry(struct super_block *sb, > } > > static struct dentry *fuse_fh_to_parent(struct super_block *sb, > - struct fid *fid, int fh_len, int fh_type) > + struct fid *fid, int fh_len, enum fid_type fh_type) > { > struct fuse_inode_handle parent; > > diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c > index 2864873..8d0d6cf 100644 > --- a/fs/gfs2/ops_export.c > +++ b/fs/gfs2/ops_export.c > @@ -31,8 +31,8 @@ > #define GFS2_LARGE_FH_SIZE 8 > #define GFS2_OLD_FH_SIZE 10 > > -static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len, > - int connectable) > +static enum fid_type gfs2_encode_fh(struct dentry *dentry, __u32 *p, > + int *len, int connectable) > { > __be32 *fh = (__force __be32 *)p; > struct inode *inode = dentry->d_inode; > @@ -41,7 +41,7 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len, > > if (*len < GFS2_SMALL_FH_SIZE || > (connectable && *len < GFS2_LARGE_FH_SIZE)) > - return 255; > + return FILEID_ERROR; > > fh[0] = cpu_to_be32(ip->i_no_formal_ino >> 32); > fh[1] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF); > @@ -50,7 +50,7 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len, > *len = GFS2_SMALL_FH_SIZE; > > if (!connectable || inode == sb->s_root->d_inode) > - return *len; > + return GFS2_SMALL_FH_SIZE; > > spin_lock(&dentry->d_lock); > inode = dentry->d_parent->d_inode; > @@ -66,7 +66,7 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len, > > iput(inode); > > - return *len; > + return GFS2_LARGE_FH_SIZE; > } > > struct get_name_filldir { > @@ -239,7 +239,7 @@ fail: > } > > static struct dentry *gfs2_fh_to_dentry(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type) > + int fh_len, enum fid_type fh_type) > { > struct gfs2_inum_host this; > __be32 *fh = (__force __be32 *)fid->raw; > @@ -259,7 +259,7 @@ static struct dentry *gfs2_fh_to_dentry(struct super_block *sb, struct fid *fid, > } > > static struct dentry *gfs2_fh_to_parent(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type) > + int fh_len, enum fid_type fh_type) > { > struct gfs2_inum_host parent; > __be32 *fh = (__force __be32 *)fid->raw; > diff --git a/fs/isofs/export.c b/fs/isofs/export.c > index 1b4ee23..3d6cfd8 100644 > --- a/fs/isofs/export.c > +++ b/fs/isofs/export.c > @@ -106,7 +106,10 @@ static struct dentry *isofs_export_get_parent(struct dentry *child) > return rv; > } > > -static int > +#define ISOFS_FILEID 1 > +#define ISOFS_FILEID_PARENT 2 > + > +static enum fid_type > isofs_export_encode_fh(struct dentry *dentry, > __u32 *fh32, > int *max_len, > @@ -115,7 +118,7 @@ isofs_export_encode_fh(struct dentry *dentry, > struct inode * inode = dentry->d_inode; > struct iso_inode_info * ei = ISOFS_I(inode); > int len = *max_len; > - int type = 1; > + enum fid_type type = ISOFS_FILEID; > __u16 *fh16 = (__u16*)fh32; > > /* > @@ -126,7 +129,7 @@ isofs_export_encode_fh(struct dentry *dentry, > */ > > if (len < 3 || (connectable && len < 5)) > - return 255; > + return FILEID_ERROR; > > len = 3; > fh32[0] = ei->i_iget5_block; > @@ -143,7 +146,7 @@ isofs_export_encode_fh(struct dentry *dentry, > fh32[4] = parent->i_generation; > spin_unlock(&dentry->d_lock); > len = 5; > - type = 2; > + type = ISOFS_FILEID_PARENT; > } > *max_len = len; > return type; > @@ -159,11 +162,11 @@ struct isofs_fid { > }; > > static struct dentry *isofs_fh_to_dentry(struct super_block *sb, > - struct fid *fid, int fh_len, int fh_type) > + struct fid *fid, int fh_len, enum fid_type fh_type) > { > struct isofs_fid *ifid = (struct isofs_fid *)fid; > > - if (fh_len < 3 || fh_type > 2) > + if (fh_len < 3 || fh_type > ISOFS_FILEID_PARENT) > return ERR_PTR(-ESTALE); > > return isofs_export_iget(sb, ifid->block, ifid->offset, > @@ -171,11 +174,11 @@ static struct dentry *isofs_fh_to_dentry(struct super_block *sb, > } > > static struct dentry *isofs_fh_to_parent(struct super_block *sb, > - struct fid *fid, int fh_len, int fh_type) > + struct fid *fid, int fh_len, enum fid_type fh_type) > { > struct isofs_fid *ifid = (struct isofs_fid *)fid; > > - if (fh_type != 2) > + if (fh_type != ISOFS_FILEID_PARENT) > return ERR_PTR(-ESTALE); > > return isofs_export_iget(sb, > diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c > index 4c4e18c..bd4998e 100644 > --- a/fs/jffs2/super.c > +++ b/fs/jffs2/super.c > @@ -73,14 +73,14 @@ static struct inode *jffs2_nfs_get_inode(struct super_block *sb, uint64_t ino, > } > > static struct dentry *jffs2_fh_to_dentry(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type) > + int fh_len, enum fid_type fh_type) > { > return generic_fh_to_dentry(sb, fid, fh_len, fh_type, > jffs2_nfs_get_inode); > } > > static struct dentry *jffs2_fh_to_parent(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type) > + int fh_len, enum fid_type fh_type) > { > return generic_fh_to_parent(sb, fid, fh_len, fh_type, > jffs2_nfs_get_inode); > diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h > index adb2faf..aa7d573 100644 > --- a/fs/jfs/jfs_inode.h > +++ b/fs/jfs/jfs_inode.h > @@ -19,6 +19,7 @@ > #define _H_JFS_INODE > > struct fid; > +enum fid_type; > > extern struct inode *ialloc(struct inode *, umode_t); > extern int jfs_fsync(struct file *, struct dentry *, int); > @@ -35,9 +36,9 @@ extern void jfs_free_zero_link(struct inode *); > extern struct dentry *jfs_get_parent(struct dentry *dentry); > extern void jfs_get_inode_flags(struct jfs_inode_info *); > extern struct dentry *jfs_fh_to_dentry(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type); > + int fh_len, enum fid_type fh_type); > extern struct dentry *jfs_fh_to_parent(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type); > + int fh_len, enum fid_type fh_type); > extern void jfs_set_inode_flags(struct inode *); > extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int); > > diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c > index cc3cedf..b824836 100644 > --- a/fs/jfs/namei.c > +++ b/fs/jfs/namei.c > @@ -1496,14 +1496,14 @@ static struct inode *jfs_nfs_get_inode(struct super_block *sb, > } > > struct dentry *jfs_fh_to_dentry(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type) > + int fh_len, enum fid_type fh_type) > { > return generic_fh_to_dentry(sb, fid, fh_len, fh_type, > jfs_nfs_get_inode); > } > > struct dentry *jfs_fh_to_parent(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type) > + int fh_len, enum fid_type fh_type) > { > return generic_fh_to_parent(sb, fid, fh_len, fh_type, > jfs_nfs_get_inode); > diff --git a/fs/libfs.c b/fs/libfs.c > index 47952f2..edb7e91 100644 > --- a/fs/libfs.c > +++ b/fs/libfs.c > @@ -745,8 +745,8 @@ out: > * inode for the object specified in the file handle. > */ > struct dentry *generic_fh_to_dentry(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type, struct inode *(*get_inode) > - (struct super_block *sb, u64 ino, u32 gen)) > + int fh_len, enum fid_type fh_type, > + exportfs_get_inode_t get_inode) > { > struct inode *inode = NULL; > > @@ -757,7 +757,6 @@ struct dentry *generic_fh_to_dentry(struct super_block *sb, struct fid *fid, > case FILEID_INO32_GEN: > case FILEID_INO32_GEN_PARENT: > inode = get_inode(sb, fid->i32.ino, fid->i32.gen); > - break; > default: > return ERR_PTR(-ESTALE); > } > @@ -780,8 +779,8 @@ EXPORT_SYMBOL_GPL(generic_fh_to_dentry); > * is specified in the file handle, or NULL otherwise. > */ > struct dentry *generic_fh_to_parent(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type, struct inode *(*get_inode) > - (struct super_block *sb, u64 ino, u32 gen)) > + int fh_len, enum fid_type fh_type, > + exportfs_get_inode_t get_inode) > { > struct inode *inode = NULL; > > @@ -792,7 +791,6 @@ struct dentry *generic_fh_to_parent(struct super_block *sb, struct fid *fid, > case FILEID_INO32_GEN_PARENT: > inode = get_inode(sb, fid->i32.parent_ino, > (fh_len > 3 ? fid->i32.parent_gen : 0)); > - break; > default: > return ERR_PTR(-ESTALE); > } > diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c > index 2ca0015..b3826c0 100644 > --- a/fs/ntfs/namei.c > +++ b/fs/ntfs/namei.c > @@ -364,14 +364,14 @@ static struct inode *ntfs_nfs_get_inode(struct super_block *sb, > } > > static struct dentry *ntfs_fh_to_dentry(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type) > + int fh_len, enum fid_type fh_type) > { > return generic_fh_to_dentry(sb, fid, fh_len, fh_type, > ntfs_nfs_get_inode); > } > > static struct dentry *ntfs_fh_to_parent(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type) > + int fh_len, enum fid_type fh_type) > { > return generic_fh_to_parent(sb, fid, fh_len, fh_type, > ntfs_nfs_get_inode); > diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c > index 0f1c80f..c03266e 100644 > --- a/fs/ocfs2/export.c > +++ b/fs/ocfs2/export.c > @@ -116,12 +116,15 @@ bail: > return parent; > } > > -static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len, > - int connectable) > +#define OCFS2_FILEID 1 > +#define OCFS2_FILEID_PARENT 2 > + > +static enum fid_type ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, > + int *max_len, int connectable) > { > struct inode *inode = dentry->d_inode; > int len = *max_len; > - int type = 1; > + enum fid_type type = OCFS2_FILEID; > u64 blkno; > u32 generation; > __le32 *fh = (__force __le32 *) fh_in; > @@ -132,7 +135,7 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len, > > if (len < 3 || (connectable && len < 6)) { > mlog(ML_ERROR, "fh buffer is too small for encoding\n"); > - type = 255; > + type = FILEID_ERROR; > goto bail; > } > > @@ -163,7 +166,7 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len, > spin_unlock(&dentry->d_lock); > > len = 6; > - type = 2; > + type = OCFS2_FILEID_PARENT; > > mlog(0, "Encoding parent: blkno: %llu, generation: %u\n", > (unsigned long long)blkno, generation); > @@ -177,11 +180,11 @@ bail: > } > > static struct dentry *ocfs2_fh_to_dentry(struct super_block *sb, > - struct fid *fid, int fh_len, int fh_type) > + struct fid *fid, int fh_len, enum fid_type fh_type) > { > struct ocfs2_inode_handle handle; > > - if (fh_len < 3 || fh_type > 2) > + if (fh_len < 3 || fh_type > OCFS2_FILEID_PARENT) > return ERR_PTR(-ESTALE); > > handle.ih_blkno = (u64)le32_to_cpu(fid->raw[0]) << 32; > @@ -191,11 +194,11 @@ static struct dentry *ocfs2_fh_to_dentry(struct super_block *sb, > } > > static struct dentry *ocfs2_fh_to_parent(struct super_block *sb, > - struct fid *fid, int fh_len, int fh_type) > + struct fid *fid, int fh_len, enum fid_type fh_type) > { > struct ocfs2_inode_handle parent; > > - if (fh_type != 2 || fh_len < 6) > + if (fh_type != OCFS2_FILEID_PARENT || fh_len < 6) > return ERR_PTR(-ESTALE); > > parent.ih_blkno = (u64)le32_to_cpu(fid->raw[3]) << 32; > diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c > index 6c4c2c6..3c548eb 100644 > --- a/fs/reiserfs/inode.c > +++ b/fs/reiserfs/inode.c > @@ -1539,7 +1539,7 @@ static struct dentry *reiserfs_get_dentry(struct super_block *sb, > } > > struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type) > + int fh_len, enum fid_type fh_type) > { > /* fhtype happens to reflect the number of u32s encoded. > * due to a bug in earlier code, fhtype might indicate there > @@ -1566,7 +1566,7 @@ struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid, > } > > struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type) > + int fh_len, enum fid_type fh_type) > { > if (fh_type < 4) > return NULL; > @@ -1577,14 +1577,14 @@ struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid, > (fh_type == 6) ? fid->raw[5] : 0); > } > > -int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp, > - int need_parent) > +enum fid_type reiserfs_encode_fh(struct dentry *dentry, __u32 * data, > + int *lenp, int need_parent) > { > struct inode *inode = dentry->d_inode; > int maxlen = *lenp; > > if (maxlen < 3) > - return 255; > + return FILEID_ERROR; > > data[0] = inode->i_ino; > data[1] = le32_to_cpu(INODE_PKEY(inode)->k_dir_id); > diff --git a/fs/udf/namei.c b/fs/udf/namei.c > index e1a1c16..afaf45e 100644 > --- a/fs/udf/namei.c > +++ b/fs/udf/namei.c > @@ -1292,7 +1292,8 @@ static struct dentry *udf_nfs_get_inode(struct super_block *sb, u32 block, > } > > static struct dentry *udf_fh_to_dentry(struct super_block *sb, > - struct fid *fid, int fh_len, int fh_type) > + struct fid *fid, int fh_len, > + enum fid_type fh_type) > { > if ((fh_len != 3 && fh_len != 5) || > (fh_type != FILEID_UDF_WITH_PARENT && > @@ -1304,7 +1305,8 @@ static struct dentry *udf_fh_to_dentry(struct super_block *sb, > } > > static struct dentry *udf_fh_to_parent(struct super_block *sb, > - struct fid *fid, int fh_len, int fh_type) > + struct fid *fid, int fh_len, > + enum fid_type fh_type) > { > if (fh_len != 5 || fh_type != FILEID_UDF_WITH_PARENT) > return ERR_PTR(-ESTALE); > @@ -1313,17 +1315,17 @@ static struct dentry *udf_fh_to_parent(struct super_block *sb, > fid->udf.parent_partref, > fid->udf.parent_generation); > } > -static int udf_encode_fh(struct dentry *de, __u32 *fh, int *lenp, > - int connectable) > +static enum fid_type udf_encode_fh(struct dentry *de, __u32 *fh, int *lenp, > + int connectable) > { > int len = *lenp; > struct inode *inode = de->d_inode; > kernel_lb_addr location = UDF_I(inode)->i_location; > struct fid *fid = (struct fid *)fh; > - int type = FILEID_UDF_WITHOUT_PARENT; > + enum fid_type type = FILEID_UDF_WITHOUT_PARENT; > > if (len < 3 || (connectable && len < 5)) > - return 255; > + return FILEID_ERROR; > > *lenp = 3; > fid->udf.block = location.logicalBlockNum; > diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c > index 7a4c75f..b15d029 100644 > --- a/fs/xfs/linux-2.6/xfs_export.c > +++ b/fs/xfs/linux-2.6/xfs_export.c > @@ -51,7 +51,7 @@ static int xfs_fileid_length(int fileid_type) > return 255; /* invalid */ > } > > -STATIC int > +STATIC enum fid_type > xfs_fs_encode_fh( > struct dentry *dentry, > __u32 *fh, > @@ -61,7 +61,7 @@ xfs_fs_encode_fh( > struct fid *fid = (struct fid *)fh; > struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fh; > struct inode *inode = dentry->d_inode; > - int fileid_type; > + enum fid_type fileid_type; > int len; > > /* Directories don't need their parent encoded, they have ".." */ > @@ -82,7 +82,7 @@ xfs_fs_encode_fh( > */ > len = xfs_fileid_length(fileid_type); > if (*max_len < len) > - return 255; > + return FILEID_ERROR; > *max_len = len; > > switch (fileid_type) { > @@ -106,6 +106,8 @@ xfs_fs_encode_fh( > fid64->ino = inode->i_ino; > fid64->gen = inode->i_generation; > break; > + default: > + break; > } > > return fileid_type; > @@ -144,7 +146,7 @@ xfs_nfs_get_inode( > > STATIC struct dentry * > xfs_fs_fh_to_dentry(struct super_block *sb, struct fid *fid, > - int fh_len, int fileid_type) > + int fh_len, enum fid_type fileid_type) > { > struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fid; > struct inode *inode = NULL; > @@ -170,7 +172,7 @@ xfs_fs_fh_to_dentry(struct super_block *sb, struct fid *fid, > > STATIC struct dentry * > xfs_fs_fh_to_parent(struct super_block *sb, struct fid *fid, > - int fh_len, int fileid_type) > + int fh_len, enum fid_type fileid_type) > { > struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fid; > struct inode *inode = NULL; > diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h > index 27e772c..d6995e8 100644 > --- a/include/linux/exportfs.h > +++ b/include/linux/exportfs.h > @@ -1,3 +1,9 @@ > +/* Persistent file handle encoding and decoding interface > + * > + * See Documentation/filesystems/Exporting for details on how to use this > + * interface correctly. > + */ > + > #ifndef LINUX_EXPORTFS_H > #define LINUX_EXPORTFS_H 1 > > @@ -9,12 +15,15 @@ struct super_block; > struct vfsmount; > > /* > - * The fileid_type identifies how the file within the filesystem is encoded. > - * In theory this is freely set and parsed by the filesystem, but we try to > - * stick to conventions so we can share some generic code and don't confuse > - * sniffers like ethereal/wireshark. > + * The fid_type identifies how the parameters specifying a file within the > + * filesystem are encoded. In theory this is freely set and parsed by the > + * filesystem, but we try to stick to conventions so we can share some generic > + * code and don't confuse sniffers like ethereal/wireshark. > * > - * The filesystem must not use the value '0' or '0xff'. > + * The filesystem may use arbitrary values rather than picking the constants > + * from this set, with the restriction that the values chosen must be between 1 > + * and 254. 0 and 255 are special purpose, and the value must fit within an > + * unsigned byte. > */ > enum fid_type { > /* > @@ -67,6 +76,10 @@ enum fid_type { > * 32 bit parent block number, 32 bit parent generation number > */ > FILEID_UDF_WITH_PARENT = 0x52, > + > + /* This is returned if the encode routine was unable to represent the > + * file */ > + FILEID_ERROR = 0xff > }; > > struct fid { > @@ -101,73 +114,97 @@ struct fid { > * this interface correctly. > * > * encode_fh: > - * @encode_fh should store in the file handle fragment @fh (using at most > - * @max_len bytes) information that can be used by @decode_fh to recover the > - * file refered to by the &struct dentry @de. If the @connectable flag is > - * set, the encode_fh() should store sufficient information so that a good > - * attempt can be made to find not only the file but also it's place in the > - * filesystem. This typically means storing a reference to de->d_parent in > - * the filehandle fragment. encode_fh() should return the number of bytes > - * stored or a negative error code such as %-ENOSPC > + * The @encode_fh operation should store into the file handle fragment > + * buffer @fh at most *@max_len 32-bit words of information that can be used > + * by fh_to_dentry() or fh_to_parent() to recover the file referred to by > + * the &struct dentry @de. > + * > + * If the @connectable flag is set, the encode_fh() should store sufficient > + * information so that a good attempt can be made to find not only the file > + * but also it's place in the filesystem. This typically means storing a > + * reference to de->d_parent in the filehandle fragment. > + * > + * On success, encode_fh() should return the type of the file handle, which > + * the caller must retain in some manner so that it can be passed to > + * decode_fh(). See the comment on enum fid_type as to the permitted types > + * that may be returned. Furthermore, *max_len should be updated upon > + * return to indicate the amount of buffer space actually filled. > + * > + * On failure FILEID_ERROR should be returned. > * > * fh_to_dentry: > - * @fh_to_dentry is given a &struct super_block (@sb) and a file handle > - * fragment (@fh, @fh_len). It should return a &struct dentry which refers > - * to the same file that the file handle fragment refers to. If it cannot, > - * it should return a %NULL pointer if the file was found but no acceptable > - * &dentries were available, or an %ERR_PTR error code indicating why it > - * couldn't be found (e.g. %ENOENT or %ENOMEM). Any suitable dentry can be > - * returned including, if necessary, a new dentry created with d_alloc_root. > - * The caller can then find any other extant dentries by following the > - * d_alias links. > + * The @fh_to_dentry operation is given a &struct super_block (@sb) and a > + * file handle fragment and type (@fh, @fh_len, @fh_type). It should look > + * up a file by the data in the partial file handle. > + * > + * On success, a pointer should be returned to a dentry that corresponds to > + * the file that the file handle fragment was generated from by encode_fh(). > + * The dentry should come from the set of dentries available to the > + * specified superblock, whether they're in memory or in storage. > + * > + * Any suitable dentry can be returned including, if necessary, a new dentry > + * created with d_alloc_root. The caller can then find any other extant > + * dentries by following the d_alias links. > + * > + * On failure, a negative error code should be returned indicating the > + * reason. Note that a NULL pointer is not a valid return. > * > * fh_to_parent: > * Same as @fh_to_dentry, except that it returns a pointer to the parent > - * dentry if it was encoded into the filehandle fragment by @encode_fh. > + * dentry if it was encoded into the filehandle fragment by encode_fh(). > * > * get_name: > * @get_name should find a name for the given @child in the given @parent > * directory. The name should be stored in the @name (with the > - * understanding that it is already pointing to a a %NAME_MAX+1 sized > - * buffer. get_name() should return %0 on success, a negative error code > - * or error. @get_name will be called without @parent->i_mutex held. > + * understanding that it is already pointing to a %NAME_MAX+1 sized buffer. > + * > + * get_name() should return zero on success and a negative error code on > + * failure. > + * > + * get_name() will be called without @parent->i_mutex held. > * > * get_parent: > * @get_parent should find the parent directory for the given @child which > * is also a directory. In the event that it cannot be found, or storage > - * space cannot be allocated, a %ERR_PTR should be returned. > + * space cannot be allocated, a suitable negative error code should be > + * returned. > * > * Locking rules: > * get_parent is called with child->d_inode->i_mutex down > * get_name is not (which is possibly inconsistent) > */ > - > struct export_operations { > - int (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len, > - int connectable); > + enum fid_type (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len, > + int connectable); > struct dentry * (*fh_to_dentry)(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type); > + int fh_len, enum fid_type fh_type); > struct dentry * (*fh_to_parent)(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type); > + int fh_len, enum fid_type fh_type); > int (*get_name)(struct dentry *parent, char *name, > struct dentry *child); > struct dentry * (*get_parent)(struct dentry *child); > }; > > -extern int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, > - int *max_len, int connectable); > +typedef int (*exportfs_acceptable_t)(void *context, struct dentry *dentry); > + > +extern enum fid_type exportfs_encode_fh(struct dentry *dentry, struct fid *fid, > + int *max_len, int connectable); > extern struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid, > - int fh_len, int fileid_type, int (*acceptable)(void *, struct dentry *), > - void *context); > + int fh_len, enum fid_type fileid_type, > + exportfs_acceptable_t acceptable, > + void *context); > > /* > * Generic helpers for filesystems. > */ > +typedef struct inode *(*exportfs_get_inode_t)(struct super_block *sb, > + u64 ino, u32 gen); > + > extern struct dentry *generic_fh_to_dentry(struct super_block *sb, > - struct fid *fid, int fh_len, int fh_type, > - struct inode *(*get_inode) (struct super_block *sb, u64 ino, u32 gen)); > + struct fid *fid, int fh_len, enum fid_type fh_type, > + exportfs_get_inode_t get_inode); > extern struct dentry *generic_fh_to_parent(struct super_block *sb, > - struct fid *fid, int fh_len, int fh_type, > - struct inode *(*get_inode) (struct super_block *sb, u64 ino, u32 gen)); > + struct fid *fid, int fh_len, enum fid_type fh_type, > + exportfs_get_inode_t get_inode); > > #endif /* LINUX_EXPORTFS_H */ > diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h > index bc5114d..0783dbe 100644 > --- a/include/linux/reiserfs_fs.h > +++ b/include/linux/reiserfs_fs.h > @@ -24,6 +24,7 @@ > #include <linux/proc_fs.h> > #include <linux/smp_lock.h> > #include <linux/buffer_head.h> > +#include <linux/exportfs.h> > #include <linux/reiserfs_fs_i.h> > #include <linux/reiserfs_fs_sb.h> > #endif > @@ -1880,11 +1881,11 @@ int reiserfs_write_inode(struct inode *inode, int); > int reiserfs_get_block(struct inode *inode, sector_t block, > struct buffer_head *bh_result, int create); > struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type); > + int fh_len, enum fid_type fh_type); > struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid, > - int fh_len, int fh_type); > -int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp, > - int connectable); > + int fh_len, enum fid_type fh_type); > +enum fid_type reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp, > + int connectable); > > int reiserfs_truncate_file(struct inode *, int update_timestamps); > void make_cpu_key(struct cpu_key *cpu_key, struct inode *inode, loff_t offset, > diff --git a/mm/shmem.c b/mm/shmem.c > index f1b0d48..d6e91dd 100644 > --- a/mm/shmem.c > +++ b/mm/shmem.c > @@ -2047,7 +2047,7 @@ static int shmem_match(struct inode *ino, void *vfh) > } > > static struct dentry *shmem_fh_to_dentry(struct super_block *sb, > - struct fid *fid, int fh_len, int fh_type) > + struct fid *fid, int fh_len, enum fid_type fh_type) > { > struct inode *inode; > struct dentry *dentry = NULL; > @@ -2067,8 +2067,8 @@ static struct dentry *shmem_fh_to_dentry(struct super_block *sb, > return dentry; > } > > -static int shmem_encode_fh(struct dentry *dentry, __u32 *fh, int *len, > - int connectable) > +static enum fid_type shmem_encode_fh(struct dentry *dentry, __u32 *fh, int *len, > + int connectable) > { > struct inode *inode = dentry->d_inode; > > > -- > 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 -- 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