diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/exportfs/expfs.c | 179 | ||||
| -rw-r--r-- | fs/nfsd/export.c | 8 |
2 files changed, 3 insertions, 184 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 | } |
