diff options
| -rw-r--r-- | fs/exportfs/expfs.c | 179 | ||||
| -rw-r--r-- | fs/nfsd/export.c | 8 | ||||
| -rw-r--r-- | include/linux/exportfs.h | 41 |
3 files changed, 3 insertions, 225 deletions
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index 99294a23cd54..e68f0279f4b0 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c | |||
| @@ -13,19 +13,6 @@ static int get_name(struct dentry *dentry, char *name, | |||
| 13 | struct dentry *child); | 13 | struct dentry *child); |
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | static struct dentry *exportfs_get_dentry(struct super_block *sb, void *obj) | ||
| 17 | { | ||
| 18 | struct dentry *result = ERR_PTR(-ESTALE); | ||
| 19 | |||
| 20 | if (sb->s_export_op->get_dentry) { | ||
| 21 | result = sb->s_export_op->get_dentry(sb, obj); | ||
| 22 | if (!result) | ||
| 23 | result = ERR_PTR(-ESTALE); | ||
| 24 | } | ||
| 25 | |||
| 26 | return result; | ||
| 27 | } | ||
| 28 | |||
| 29 | static int exportfs_get_name(struct dentry *dir, char *name, | 16 | static int exportfs_get_name(struct dentry *dir, char *name, |
| 30 | struct dentry *child) | 17 | struct dentry *child) |
| 31 | { | 18 | { |
| @@ -214,125 +201,6 @@ reconnect_path(struct super_block *sb, struct dentry *target_dir) | |||
| 214 | return 0; | 201 | return 0; |
| 215 | } | 202 | } |
| 216 | 203 | ||
| 217 | /** | ||
| 218 | * find_exported_dentry - helper routine to implement export_operations->decode_fh | ||
| 219 | * @sb: The &super_block identifying the filesystem | ||
| 220 | * @obj: An opaque identifier of the object to be found - passed to | ||
| 221 | * get_inode | ||
| 222 | * @parent: An optional opqaue identifier of the parent of the object. | ||
| 223 | * @acceptable: A function used to test possible &dentries to see if they are | ||
| 224 | * acceptable | ||
| 225 | * @context: A parameter to @acceptable so that it knows on what basis to | ||
| 226 | * judge. | ||
| 227 | * | ||
| 228 | * find_exported_dentry is the central helper routine to enable file systems | ||
| 229 | * to provide the decode_fh() export_operation. It's main task is to take | ||
| 230 | * an &inode, find or create an appropriate &dentry structure, and possibly | ||
| 231 | * splice this into the dcache in the correct place. | ||
| 232 | * | ||
| 233 | * The decode_fh() operation provided by the filesystem should call | ||
| 234 | * find_exported_dentry() with the same parameters that it received except | ||
| 235 | * that instead of the file handle fragment, pointers to opaque identifiers | ||
| 236 | * for the object and optionally its parent are passed. The default decode_fh | ||
| 237 | * routine passes one pointer to the start of the filehandle fragment, and | ||
| 238 | * one 8 bytes into the fragment. It is expected that most filesystems will | ||
| 239 | * take this approach, though the offset to the parent identifier may well be | ||
| 240 | * different. | ||
| 241 | * | ||
| 242 | * find_exported_dentry() will call get_dentry to get an dentry pointer from | ||
| 243 | * the file system. If any &dentry in the d_alias list is acceptable, it will | ||
| 244 | * be returned. Otherwise find_exported_dentry() will attempt to splice a new | ||
| 245 | * &dentry into the dcache using get_name() and get_parent() to find the | ||
| 246 | * appropriate place. | ||
| 247 | */ | ||
| 248 | |||
| 249 | struct dentry * | ||
| 250 | find_exported_dentry(struct super_block *sb, void *obj, void *parent, | ||
| 251 | int (*acceptable)(void *context, struct dentry *de), | ||
| 252 | void *context) | ||
| 253 | { | ||
| 254 | struct dentry *result, *alias; | ||
| 255 | int err = -ESTALE; | ||
| 256 | |||
| 257 | /* | ||
| 258 | * Attempt to find the inode. | ||
| 259 | */ | ||
| 260 | result = exportfs_get_dentry(sb, obj); | ||
| 261 | if (IS_ERR(result)) | ||
| 262 | return result; | ||
| 263 | |||
| 264 | if (S_ISDIR(result->d_inode->i_mode)) { | ||
| 265 | if (!(result->d_flags & DCACHE_DISCONNECTED)) { | ||
| 266 | if (acceptable(context, result)) | ||
| 267 | return result; | ||
| 268 | err = -EACCES; | ||
| 269 | goto err_result; | ||
| 270 | } | ||
| 271 | |||
| 272 | err = reconnect_path(sb, result); | ||
| 273 | if (err) | ||
| 274 | goto err_result; | ||
| 275 | } else { | ||
| 276 | struct dentry *target_dir, *nresult; | ||
| 277 | char nbuf[NAME_MAX+1]; | ||
| 278 | |||
| 279 | alias = find_acceptable_alias(result, acceptable, context); | ||
| 280 | if (alias) | ||
| 281 | return alias; | ||
| 282 | |||
| 283 | if (parent == NULL) | ||
| 284 | goto err_result; | ||
| 285 | |||
| 286 | target_dir = exportfs_get_dentry(sb,parent); | ||
| 287 | if (IS_ERR(target_dir)) { | ||
| 288 | err = PTR_ERR(target_dir); | ||
| 289 | goto err_result; | ||
| 290 | } | ||
| 291 | |||
| 292 | err = reconnect_path(sb, target_dir); | ||
| 293 | if (err) { | ||
| 294 | dput(target_dir); | ||
| 295 | goto err_result; | ||
| 296 | } | ||
| 297 | |||
| 298 | /* | ||
| 299 | * As we weren't after a directory, have one more step to go. | ||
| 300 | */ | ||
| 301 | err = exportfs_get_name(target_dir, nbuf, result); | ||
| 302 | if (!err) { | ||
| 303 | mutex_lock(&target_dir->d_inode->i_mutex); | ||
| 304 | nresult = lookup_one_len(nbuf, target_dir, | ||
| 305 | strlen(nbuf)); | ||
| 306 | mutex_unlock(&target_dir->d_inode->i_mutex); | ||
| 307 | if (!IS_ERR(nresult)) { | ||
| 308 | if (nresult->d_inode) { | ||
| 309 | dput(result); | ||
| 310 | result = nresult; | ||
| 311 | } else | ||
| 312 | dput(nresult); | ||
| 313 | } | ||
| 314 | } | ||
| 315 | dput(target_dir); | ||
| 316 | } | ||
| 317 | |||
| 318 | alias = find_acceptable_alias(result, acceptable, context); | ||
| 319 | if (alias) | ||
| 320 | return alias; | ||
| 321 | |||
| 322 | /* drat - I just cannot find anything acceptable */ | ||
| 323 | dput(result); | ||
| 324 | /* It might be justifiable to return ESTALE here, | ||
| 325 | * but the filehandle at-least looks reasonable good | ||
| 326 | * and it may just be a permission problem, so returning | ||
| 327 | * -EACCESS is safer | ||
| 328 | */ | ||
| 329 | return ERR_PTR(-EACCES); | ||
| 330 | |||
| 331 | err_result: | ||
| 332 | dput(result); | ||
| 333 | return ERR_PTR(err); | ||
| 334 | } | ||
| 335 | |||
| 336 | struct getdents_callback { | 204 | struct getdents_callback { |
| 337 | char *name; /* name that was found. It already points to a | 205 | char *name; /* name that was found. It already points to a |
| 338 | buffer NAME_MAX+1 is size */ | 206 | buffer NAME_MAX+1 is size */ |
| @@ -462,38 +330,6 @@ static int export_encode_fh(struct dentry *dentry, struct fid *fid, | |||
| 462 | return type; | 330 | return type; |
| 463 | } | 331 | } |
| 464 | 332 | ||
| 465 | |||
| 466 | /** | ||
| 467 | * export_decode_fh - default export_operations->decode_fh function | ||
| 468 | * @sb: The superblock | ||
| 469 | * @fh: pointer to the file handle fragment | ||
| 470 | * @fh_len: length of file handle fragment | ||
| 471 | * @acceptable: function for testing acceptability of dentrys | ||
| 472 | * @context: context for @acceptable | ||
| 473 | * | ||
| 474 | * This is the default decode_fh() function. | ||
| 475 | * a fileid_type of 1 indicates that the filehandlefragment | ||
| 476 | * just contains an object identifier understood by get_dentry. | ||
| 477 | * a fileid_type of 2 says that there is also a directory | ||
| 478 | * identifier 8 bytes in to the filehandlefragement. | ||
| 479 | */ | ||
| 480 | static struct dentry *export_decode_fh(struct super_block *sb, __u32 *fh, int fh_len, | ||
| 481 | int fileid_type, | ||
| 482 | int (*acceptable)(void *context, struct dentry *de), | ||
| 483 | void *context) | ||
| 484 | { | ||
| 485 | __u32 parent[2]; | ||
| 486 | parent[0] = parent[1] = 0; | ||
| 487 | if (fh_len < 2 || fileid_type > 2) | ||
| 488 | return NULL; | ||
| 489 | if (fileid_type == 2) { | ||
| 490 | if (fh_len > 2) parent[0] = fh[2]; | ||
| 491 | if (fh_len > 3) parent[1] = fh[3]; | ||
| 492 | } | ||
| 493 | return find_exported_dentry(sb, fh, parent, | ||
| 494 | acceptable, context); | ||
| 495 | } | ||
| 496 | |||
| 497 | int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len, | 333 | int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len, |
| 498 | int connectable) | 334 | int connectable) |
| 499 | { | 335 | { |
| @@ -518,19 +354,6 @@ struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid, | |||
| 518 | int err; | 354 | int err; |
| 519 | 355 | ||
| 520 | /* | 356 | /* |
| 521 | * Old way of doing things. Will go away soon. | ||
| 522 | */ | ||
| 523 | if (!nop->fh_to_dentry) { | ||
| 524 | if (nop->decode_fh) { | ||
| 525 | return nop->decode_fh(mnt->mnt_sb, fid->raw, fh_len, | ||
| 526 | fileid_type, acceptable, context); | ||
| 527 | } else { | ||
| 528 | return export_decode_fh(mnt->mnt_sb, fid->raw, fh_len, | ||
| 529 | fileid_type, acceptable, context); | ||
| 530 | } | ||
| 531 | } | ||
| 532 | |||
| 533 | /* | ||
| 534 | * Try to get any dentry for the given file handle from the filesystem. | 357 | * Try to get any dentry for the given file handle from the filesystem. |
| 535 | */ | 358 | */ |
| 536 | result = nop->fh_to_dentry(mnt->mnt_sb, fid, fh_len, fileid_type); | 359 | result = nop->fh_to_dentry(mnt->mnt_sb, fid, fh_len, fileid_type); |
| @@ -652,6 +475,4 @@ struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid, | |||
| 652 | } | 475 | } |
| 653 | EXPORT_SYMBOL_GPL(exportfs_decode_fh); | 476 | EXPORT_SYMBOL_GPL(exportfs_decode_fh); |
| 654 | 477 | ||
| 655 | EXPORT_SYMBOL(find_exported_dentry); | ||
| 656 | |||
| 657 | MODULE_LICENSE("GPL"); | 478 | MODULE_LICENSE("GPL"); |
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 04b266729802..66d0aeb32a47 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
| @@ -386,15 +386,13 @@ static int check_export(struct inode *inode, int flags, unsigned char *uuid) | |||
| 386 | dprintk("exp_export: export of non-dev fs without fsid\n"); | 386 | dprintk("exp_export: export of non-dev fs without fsid\n"); |
| 387 | return -EINVAL; | 387 | return -EINVAL; |
| 388 | } | 388 | } |
| 389 | if (!inode->i_sb->s_export_op) { | 389 | |
| 390 | if (!inode->i_sb->s_export_op || | ||
| 391 | !inode->i_sb->s_export_op->fh_to_dentry) { | ||
| 390 | dprintk("exp_export: export of invalid fs type.\n"); | 392 | dprintk("exp_export: export of invalid fs type.\n"); |
| 391 | return -EINVAL; | 393 | return -EINVAL; |
| 392 | } | 394 | } |
| 393 | 395 | ||
| 394 | /* Ok, we can export it */; | ||
| 395 | if (!inode->i_sb->s_export_op->find_exported_dentry) | ||
| 396 | inode->i_sb->s_export_op->find_exported_dentry = | ||
| 397 | find_exported_dentry; | ||
| 398 | return 0; | 396 | return 0; |
| 399 | 397 | ||
| 400 | } | 398 | } |
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h index b44f6b6871c8..0b4a771b4903 100644 --- a/include/linux/exportfs.h +++ b/include/linux/exportfs.h | |||
| @@ -54,8 +54,6 @@ struct fid { | |||
| 54 | * @get_name: find the name for a given inode in a given directory | 54 | * @get_name: find the name for a given inode in a given directory |
| 55 | * @get_parent: find the parent of a given directory | 55 | * @get_parent: find the parent of a given directory |
| 56 | * @get_dentry: find a dentry for the inode given a file handle sub-fragment | 56 | * @get_dentry: find a dentry for the inode given a file handle sub-fragment |
| 57 | * @find_exported_dentry: | ||
| 58 | * set by the exporting module to a standard helper function. | ||
| 59 | * | 57 | * |
| 60 | * Description: | 58 | * Description: |
| 61 | * The export_operations structure provides a means for nfsd to communicate | 59 | * The export_operations structure provides a means for nfsd to communicate |
| @@ -82,16 +80,6 @@ struct fid { | |||
| 82 | * looking for the next. As soon as an acceptable one is found, it should | 80 | * looking for the next. As soon as an acceptable one is found, it should |
| 83 | * be returned. | 81 | * be returned. |
| 84 | * | 82 | * |
| 85 | * decode_fh: | ||
| 86 | * @decode_fh is given a &struct super_block (@sb), a file handle fragment | ||
| 87 | * (@fh, @fh_len) and an acceptability testing function (@acceptable, | ||
| 88 | * @context). It should return a &struct dentry which refers to the same | ||
| 89 | * file that the file handle fragment refers to, and which passes the | ||
| 90 | * acceptability test. If it cannot, it should return a %NULL pointer if | ||
| 91 | * the file was found but no acceptable &dentries were available, or a | ||
| 92 | * %ERR_PTR error code indicating why it couldn't be found (e.g. %ENOENT or | ||
| 93 | * %ENOMEM). | ||
| 94 | * | ||
| 95 | * encode_fh: | 83 | * encode_fh: |
| 96 | * @encode_fh should store in the file handle fragment @fh (using at most | 84 | * @encode_fh should store in the file handle fragment @fh (using at most |
| 97 | * @max_len bytes) information that can be used by @decode_fh to recover the | 85 | * @max_len bytes) information that can be used by @decode_fh to recover the |
| @@ -129,30 +117,12 @@ struct fid { | |||
| 129 | * is also a directory. In the event that it cannot be found, or storage | 117 | * is also a directory. In the event that it cannot be found, or storage |
| 130 | * space cannot be allocated, a %ERR_PTR should be returned. | 118 | * space cannot be allocated, a %ERR_PTR should be returned. |
| 131 | * | 119 | * |
| 132 | * get_dentry: | ||
| 133 | * Given a &super_block (@sb) and a pointer to a file-system specific inode | ||
| 134 | * identifier, possibly an inode number, (@inump) get_dentry() should find | ||
| 135 | * the identified inode and return a dentry for that inode. Any suitable | ||
| 136 | * dentry can be returned including, if necessary, a new dentry created with | ||
| 137 | * d_alloc_root. The caller can then find any other extant dentrys by | ||
| 138 | * following the d_alias links. If a new dentry was created using | ||
| 139 | * d_alloc_root, DCACHE_NFSD_DISCONNECTED should be set, and the dentry | ||
| 140 | * should be d_rehash()ed. | ||
| 141 | * | ||
| 142 | * If the inode cannot be found, either a %NULL pointer or an %ERR_PTR code | ||
| 143 | * can be returned. The @inump will be whatever was passed to | ||
| 144 | * nfsd_find_fh_dentry() in either the @obj or @parent parameters. | ||
| 145 | * | ||
| 146 | * Locking rules: | 120 | * Locking rules: |
| 147 | * get_parent is called with child->d_inode->i_mutex down | 121 | * get_parent is called with child->d_inode->i_mutex down |
| 148 | * get_name is not (which is possibly inconsistent) | 122 | * get_name is not (which is possibly inconsistent) |
| 149 | */ | 123 | */ |
| 150 | 124 | ||
| 151 | struct export_operations { | 125 | struct export_operations { |
| 152 | struct dentry *(*decode_fh)(struct super_block *sb, __u32 *fh, | ||
| 153 | int fh_len, int fh_type, | ||
| 154 | int (*acceptable)(void *context, struct dentry *de), | ||
| 155 | void *context); | ||
| 156 | int (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len, | 126 | int (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len, |
| 157 | int connectable); | 127 | int connectable); |
| 158 | struct dentry * (*fh_to_dentry)(struct super_block *sb, struct fid *fid, | 128 | struct dentry * (*fh_to_dentry)(struct super_block *sb, struct fid *fid, |
| @@ -162,19 +132,8 @@ struct export_operations { | |||
| 162 | int (*get_name)(struct dentry *parent, char *name, | 132 | int (*get_name)(struct dentry *parent, char *name, |
| 163 | struct dentry *child); | 133 | struct dentry *child); |
| 164 | struct dentry * (*get_parent)(struct dentry *child); | 134 | struct dentry * (*get_parent)(struct dentry *child); |
| 165 | struct dentry * (*get_dentry)(struct super_block *sb, void *inump); | ||
| 166 | |||
| 167 | /* This is set by the exporting module to a standard helper */ | ||
| 168 | struct dentry * (*find_exported_dentry)( | ||
| 169 | struct super_block *sb, void *obj, void *parent, | ||
| 170 | int (*acceptable)(void *context, struct dentry *de), | ||
| 171 | void *context); | ||
| 172 | }; | 135 | }; |
| 173 | 136 | ||
| 174 | extern struct dentry *find_exported_dentry(struct super_block *sb, void *obj, | ||
| 175 | void *parent, int (*acceptable)(void *context, struct dentry *de), | ||
| 176 | void *context); | ||
| 177 | |||
| 178 | extern int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, | 137 | extern int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, |
| 179 | int *max_len, int connectable); | 138 | int *max_len, int connectable); |
| 180 | extern struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid, | 139 | extern struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid, |
