Commit 537ad07f authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[PATCH] PATCH - kNFSd/FAT in 2.5.14 - Add export_operations support for FAT

This actually contains a lot of code that is never used,
as we don't currently attempt to load an inode that isn't
in cache, so the fat_get_parent is never actually reached.
However it is there (and should be right) incase some brave
soul does decide to enhance fat_get_dentry accordingly.
parent 6f9a2db9
...@@ -438,20 +438,26 @@ static int fat_read_root(struct inode *inode) ...@@ -438,20 +438,26 @@ static int fat_read_root(struct inode *inode)
* 4/ parent->i_logstart - maybe used to hunt for the file on disc * 4/ parent->i_logstart - maybe used to hunt for the file on disc
* *
*/ */
struct dentry *fat_fh_to_dentry(struct super_block *sb, __u32 *fh,
int len, int fhtype, int parent) struct dentry *fat_decode_fh(struct super_block *sb, __u32 *fh,
int len, int fhtype,
int (*acceptable)(void *context, struct dentry *de),
void *context)
{ {
struct inode *inode = NULL;
struct dentry *result;
if (fhtype != 3) if (fhtype != 3)
return ERR_PTR(-ESTALE); return ERR_PTR(-ESTALE);
if (len < 5) if (len < 5)
return ERR_PTR(-ESTALE); return ERR_PTR(-ESTALE);
/* We cannot find the parent,
It better just *be* there */ return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable, context);
if (parent) }
return ERR_PTR(-ESTALE);
struct dentry *fat_get_dentry(struct super_block *sb, void *inump)
{
struct inode *inode = NULL;
struct dentry *result;
__u32 *fh = inump;
inode = iget(sb, fh[0]); inode = iget(sb, fh[0]);
if (!inode || is_bad_inode(inode) || if (!inode || is_bad_inode(inode) ||
...@@ -497,12 +503,13 @@ struct dentry *fat_fh_to_dentry(struct super_block *sb, __u32 *fh, ...@@ -497,12 +503,13 @@ struct dentry *fat_fh_to_dentry(struct super_block *sb, __u32 *fh,
iput(inode); iput(inode);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
result->d_op = sb->s_root->d_op;
result->d_vfs_flags |= DCACHE_REFERENCED; result->d_vfs_flags |= DCACHE_REFERENCED;
return result; return result;
} }
int fat_dentry_to_fh(struct dentry *de, __u32 *fh, int *lenp, int needparent) int fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable)
{ {
int len = *lenp; int len = *lenp;
struct inode *inode = de->d_inode; struct inode *inode = de->d_inode;
...@@ -520,6 +527,43 @@ int fat_dentry_to_fh(struct dentry *de, __u32 *fh, int *lenp, int needparent) ...@@ -520,6 +527,43 @@ int fat_dentry_to_fh(struct dentry *de, __u32 *fh, int *lenp, int needparent)
return 3; return 3;
} }
struct dentry *fat_get_parent(struct dentry *child)
{
struct buffer_head *bh=NULL;
struct msdos_dir_entry *de = NULL;
struct dentry *parent = NULL;
int res;
int ino = 0;
struct inode *inode;
lock_kernel();
res = fat_scan(child->d_inode, MSDOS_DOTDOT, &bh, &de, &ino);
if (res < 0)
goto out;
inode = fat_build_inode(child->d_sb, de, ino, &res);
if (res)
goto out;
if (!inode)
res = -EACCES;
else {
parent = d_alloc_anon(inode);
if (!parent) {
iput(inode);
res = -ENOMEM;
}
}
out:
if(bh)
fat_brelse(child->d_sb, bh);
unlock_kernel();
if (res)
return ERR_PTR(res);
else
return parent;
}
static kmem_cache_t *fat_inode_cachep; static kmem_cache_t *fat_inode_cachep;
static struct inode *fat_alloc_inode(struct super_block *sb) static struct inode *fat_alloc_inode(struct super_block *sb)
...@@ -574,8 +618,13 @@ static struct super_operations fat_sops = { ...@@ -574,8 +618,13 @@ static struct super_operations fat_sops = {
clear_inode: fat_clear_inode, clear_inode: fat_clear_inode,
read_inode: make_bad_inode, read_inode: make_bad_inode,
fh_to_dentry: fat_fh_to_dentry, };
dentry_to_fh: fat_dentry_to_fh,
static struct export_operations fat_export_ops = {
decode_fh: fat_decode_fh,
encode_fh: fat_encode_fh,
get_dentry: fat_get_dentry,
get_parent: fat_get_parent,
}; };
/* /*
...@@ -609,6 +658,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, ...@@ -609,6 +658,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
sb->s_magic = MSDOS_SUPER_MAGIC; sb->s_magic = MSDOS_SUPER_MAGIC;
sb->s_op = &fat_sops; sb->s_op = &fat_sops;
sb->s_export_op = &fat_export_ops;
sbi->options.isvfat = isvfat; sbi->options.isvfat = isvfat;
sbi->dir_ops = fs_dir_inode_ops; sbi->dir_ops = fs_dir_inode_ops;
sbi->cvf_format = &default_cvf; sbi->cvf_format = &default_cvf;
......
...@@ -221,13 +221,22 @@ struct dentry *msdos_lookup(struct inode *dir,struct dentry *dentry) ...@@ -221,13 +221,22 @@ struct dentry *msdos_lookup(struct inode *dir,struct dentry *dentry)
if (res) if (res)
goto out; goto out;
add: add:
d_add(dentry, inode); if (inode) {
dentry = d_splice_alias(inode, dentry);
dentry->d_op = &msdos_dentry_operations;
} else {
d_add(dentry, inode);
dentry = NULL;
}
res = 0; res = 0;
out: out:
if (bh) if (bh)
fat_brelse(sb, bh); fat_brelse(sb, bh);
unlock_kernel(); unlock_kernel();
return ERR_PTR(res); if (res)
return ERR_PTR(res);
else
return dentry;
} }
/***** Creates a directory entry (name is already formatted). */ /***** Creates a directory entry (name is already formatted). */
......
...@@ -1020,6 +1020,14 @@ struct dentry *vfat_lookup(struct inode *dir,struct dentry *dentry) ...@@ -1020,6 +1020,14 @@ struct dentry *vfat_lookup(struct inode *dir,struct dentry *dentry)
unlock_kernel(); unlock_kernel();
dentry->d_op = &vfat_dentry_ops[table]; dentry->d_op = &vfat_dentry_ops[table];
dentry->d_time = dentry->d_parent->d_inode->i_version; dentry->d_time = dentry->d_parent->d_inode->i_version;
if (inode) {
dentry = d_splice_alias(inode, dentry);
if (dentry) {
dentry->d_op = &vfat_dentry_ops[table];
dentry->d_time = dentry->d_parent->d_inode->i_version;
}
return dentry;
}
d_add(dentry,inode); d_add(dentry,inode);
return NULL; return NULL;
} }
...@@ -1305,11 +1313,11 @@ int vfat_fill_super(struct super_block *sb, void *data, int silent) ...@@ -1305,11 +1313,11 @@ int vfat_fill_super(struct super_block *sb, void *data, int silent)
if (sbi->options.posixfs) { if (sbi->options.posixfs) {
sbi->options.name_check = 's'; sbi->options.name_check = 's';
} }
if (sbi->options.name_check != 's') { }
sb->s_root->d_op = &vfat_dentry_ops[0]; if (sbi->options.name_check != 's') {
} else { sb->s_root->d_op = &vfat_dentry_ops[0];
sb->s_root->d_op = &vfat_dentry_ops[2]; } else {
} sb->s_root->d_op = &vfat_dentry_ops[2];
} }
return 0; return 0;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment