diff options
Diffstat (limited to 'fs/exofs')
-rw-r--r-- | fs/exofs/dir.c | 15 | ||||
-rw-r--r-- | fs/exofs/exofs.h | 1 | ||||
-rw-r--r-- | fs/exofs/super.c | 53 |
3 files changed, 69 insertions, 0 deletions
diff --git a/fs/exofs/dir.c b/fs/exofs/dir.c index 6865605fb6ab..65b0c8c776a1 100644 --- a/fs/exofs/dir.c +++ b/fs/exofs/dir.c | |||
@@ -381,6 +381,21 @@ struct exofs_dir_entry *exofs_dotdot(struct inode *dir, struct page **p) | |||
381 | return de; | 381 | return de; |
382 | } | 382 | } |
383 | 383 | ||
384 | ino_t exofs_parent_ino(struct dentry *child) | ||
385 | { | ||
386 | struct page *page; | ||
387 | struct exofs_dir_entry *de; | ||
388 | ino_t ino; | ||
389 | |||
390 | de = exofs_dotdot(child->d_inode, &page); | ||
391 | if (!de) | ||
392 | return 0; | ||
393 | |||
394 | ino = le64_to_cpu(de->inode_no); | ||
395 | exofs_put_page(page); | ||
396 | return ino; | ||
397 | } | ||
398 | |||
384 | ino_t exofs_inode_by_name(struct inode *dir, struct dentry *dentry) | 399 | ino_t exofs_inode_by_name(struct inode *dir, struct dentry *dentry) |
385 | { | 400 | { |
386 | ino_t res = 0; | 401 | ino_t res = 0; |
diff --git a/fs/exofs/exofs.h b/fs/exofs/exofs.h index 11e11d5c97ba..0fd4c7859679 100644 --- a/fs/exofs/exofs.h +++ b/fs/exofs/exofs.h | |||
@@ -152,6 +152,7 @@ struct exofs_dir_entry *exofs_find_entry(struct inode *, struct dentry *, | |||
152 | struct page **); | 152 | struct page **); |
153 | int exofs_empty_dir(struct inode *); | 153 | int exofs_empty_dir(struct inode *); |
154 | struct exofs_dir_entry *exofs_dotdot(struct inode *, struct page **); | 154 | struct exofs_dir_entry *exofs_dotdot(struct inode *, struct page **); |
155 | ino_t exofs_parent_ino(struct dentry *child); | ||
155 | int exofs_set_link(struct inode *, struct exofs_dir_entry *, struct page *, | 156 | int exofs_set_link(struct inode *, struct exofs_dir_entry *, struct page *, |
156 | struct inode *); | 157 | struct inode *); |
157 | 158 | ||
diff --git a/fs/exofs/super.c b/fs/exofs/super.c index b736b117a2a4..9f1985e857e2 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/parser.h> | 37 | #include <linux/parser.h> |
38 | #include <linux/vfs.h> | 38 | #include <linux/vfs.h> |
39 | #include <linux/random.h> | 39 | #include <linux/random.h> |
40 | #include <linux/exportfs.h> | ||
40 | 41 | ||
41 | #include "exofs.h" | 42 | #include "exofs.h" |
42 | 43 | ||
@@ -194,6 +195,7 @@ static void destroy_inodecache(void) | |||
194 | * SUPERBLOCK FUNCTIONS | 195 | * SUPERBLOCK FUNCTIONS |
195 | *****************************************************************************/ | 196 | *****************************************************************************/ |
196 | static const struct super_operations exofs_sops; | 197 | static const struct super_operations exofs_sops; |
198 | static const struct export_operations exofs_export_ops; | ||
197 | 199 | ||
198 | /* | 200 | /* |
199 | * Write the superblock to the OSD | 201 | * Write the superblock to the OSD |
@@ -358,6 +360,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) | |||
358 | 360 | ||
359 | /* set up operation vectors */ | 361 | /* set up operation vectors */ |
360 | sb->s_op = &exofs_sops; | 362 | sb->s_op = &exofs_sops; |
363 | sb->s_export_op = &exofs_export_ops; | ||
361 | root = exofs_iget(sb, EXOFS_ROOT_ID - EXOFS_OBJ_OFF); | 364 | root = exofs_iget(sb, EXOFS_ROOT_ID - EXOFS_OBJ_OFF); |
362 | if (IS_ERR(root)) { | 365 | if (IS_ERR(root)) { |
363 | EXOFS_ERR("ERROR: exofs_iget failed\n"); | 366 | EXOFS_ERR("ERROR: exofs_iget failed\n"); |
@@ -485,6 +488,56 @@ static const struct super_operations exofs_sops = { | |||
485 | }; | 488 | }; |
486 | 489 | ||
487 | /****************************************************************************** | 490 | /****************************************************************************** |
491 | * EXPORT OPERATIONS | ||
492 | *****************************************************************************/ | ||
493 | |||
494 | struct dentry *exofs_get_parent(struct dentry *child) | ||
495 | { | ||
496 | unsigned long ino = exofs_parent_ino(child); | ||
497 | |||
498 | if (!ino) | ||
499 | return NULL; | ||
500 | |||
501 | return d_obtain_alias(exofs_iget(child->d_inode->i_sb, ino)); | ||
502 | } | ||
503 | |||
504 | static struct inode *exofs_nfs_get_inode(struct super_block *sb, | ||
505 | u64 ino, u32 generation) | ||
506 | { | ||
507 | struct inode *inode; | ||
508 | |||
509 | inode = exofs_iget(sb, ino); | ||
510 | if (IS_ERR(inode)) | ||
511 | return ERR_CAST(inode); | ||
512 | if (generation && inode->i_generation != generation) { | ||
513 | /* we didn't find the right inode.. */ | ||
514 | iput(inode); | ||
515 | return ERR_PTR(-ESTALE); | ||
516 | } | ||
517 | return inode; | ||
518 | } | ||
519 | |||
520 | static struct dentry *exofs_fh_to_dentry(struct super_block *sb, | ||
521 | struct fid *fid, int fh_len, int fh_type) | ||
522 | { | ||
523 | return generic_fh_to_dentry(sb, fid, fh_len, fh_type, | ||
524 | exofs_nfs_get_inode); | ||
525 | } | ||
526 | |||
527 | static struct dentry *exofs_fh_to_parent(struct super_block *sb, | ||
528 | struct fid *fid, int fh_len, int fh_type) | ||
529 | { | ||
530 | return generic_fh_to_parent(sb, fid, fh_len, fh_type, | ||
531 | exofs_nfs_get_inode); | ||
532 | } | ||
533 | |||
534 | static const struct export_operations exofs_export_ops = { | ||
535 | .fh_to_dentry = exofs_fh_to_dentry, | ||
536 | .fh_to_parent = exofs_fh_to_parent, | ||
537 | .get_parent = exofs_get_parent, | ||
538 | }; | ||
539 | |||
540 | /****************************************************************************** | ||
488 | * INSMOD/RMMOD | 541 | * INSMOD/RMMOD |
489 | *****************************************************************************/ | 542 | *****************************************************************************/ |
490 | 543 | ||