Commit 6033f024 authored by Linus Torvalds's avatar Linus Torvalds

Merge

parents 80be2217 9b406173
...@@ -115,7 +115,7 @@ statfs: yes no no ...@@ -115,7 +115,7 @@ statfs: yes no no
remount_fs: yes yes maybe (see below) remount_fs: yes yes maybe (see below)
umount_begin: yes no maybe (see below) umount_begin: yes no maybe (see below)
->read_inode() is not a method - it's a callback used in iget()/iget4(). ->read_inode() is not a method - it's a callback used in iget().
rules for mount_sem are not too nice - it is going to die and be replaced rules for mount_sem are not too nice - it is going to die and be replaced
by better scheme anyway. by better scheme anyway.
......
...@@ -152,3 +152,38 @@ settles down a bit. ...@@ -152,3 +152,38 @@ settles down a bit.
s_export_op is now required for exporting a filesystem. s_export_op is now required for exporting a filesystem.
isofs, ext2, ext3, resierfs, fat isofs, ext2, ext3, resierfs, fat
can be used as examples of very different filesystems. can be used as examples of very different filesystems.
---
[mandatory]
iget4() and the read_inode2 callback have been superseded by iget5_locked()
which has the following prototype,
struct inode *iget5_locked(struct super_block *sb, unsigned long ino,
int (*test)(struct inode *, void *),
int (*set)(struct inode *, void *),
void *data);
'test' is an additional function that can be used when the inode
number is not sufficient to identify the actual file object. 'set'
should be a non-blocking function that initializes those parts of a
newly created inode to allow the test function to succeed. 'data' is
passed as an opaque value to both test and set functions.
When the inode has been created by iget5_locked(), it will be returned with
the I_NEW flag set and will still be locked. read_inode has not been
called so the file system still has to finalize the initialization. Once
the inode is initialized it must be unlocked by calling unlock_new_inode().
The filesystem is responsible for setting (and possibly testing) i_ino
when appropriate. There is also a simpler iget_locked function that
just takes the superblock and inode number as arguments and does the
test and set for you.
e.g.
inode = iget_locked(sb, ino);
if (inode->i_state & I_NEW) {
read_inode_from_disk(inode);
unlock_new_inode(inode);
}
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
O_TARGET := fs.o O_TARGET := fs.o
export-objs := filesystems.o open.o dcache.o buffer.o bio.o export-objs := filesystems.o open.o dcache.o buffer.o bio.o inode.o
mod-subdirs := nls mod-subdirs := nls
obj-y := open.o read_write.o devices.o file_table.o buffer.o \ obj-y := open.o read_write.o devices.o file_table.o buffer.o \
......
...@@ -25,11 +25,6 @@ inline int coda_isnullfid(ViceFid *fid) ...@@ -25,11 +25,6 @@ inline int coda_isnullfid(ViceFid *fid)
return 1; return 1;
} }
static int coda_inocmp(struct inode *inode, unsigned long ino, void *opaque)
{
return (coda_fideq((ViceFid *)opaque, &(ITOC(inode)->c_fid)));
}
static struct inode_operations coda_symlink_inode_operations = { static struct inode_operations coda_symlink_inode_operations = {
readlink: page_readlink, readlink: page_readlink,
follow_link: page_follow_link, follow_link: page_follow_link,
...@@ -55,26 +50,44 @@ static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr) ...@@ -55,26 +50,44 @@ static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
init_special_inode(inode, inode->i_mode, attr->va_rdev); init_special_inode(inode, inode->i_mode, attr->va_rdev);
} }
static int coda_test_inode(struct inode *inode, void *data)
{
ViceFid *fid = (ViceFid *)data;
return coda_fideq(&(ITOC(inode)->c_fid), fid);
}
static int coda_set_inode(struct inode *inode, void *data)
{
ViceFid *fid = (ViceFid *)data;
ITOC(inode)->c_fid = *fid;
return 0;
}
static int coda_fail_inode(struct inode *inode, void *data)
{
return -1;
}
struct inode * coda_iget(struct super_block * sb, ViceFid * fid, struct inode * coda_iget(struct super_block * sb, ViceFid * fid,
struct coda_vattr * attr) struct coda_vattr * attr)
{ {
struct inode *inode; struct inode *inode;
struct coda_inode_info *cii; struct coda_inode_info *cii;
ino_t ino = coda_f2i(fid); struct coda_sb_info *sbi = coda_sbp(sb);
unsigned long hash = coda_f2i(fid);
inode = iget4(sb, ino, coda_inocmp, fid); inode = iget5_locked(sb, hash, coda_test_inode, coda_set_inode, fid);
if (!inode) if (!inode)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
/* check if the inode is already initialized */ if (inode->i_state & I_NEW) {
cii = ITOC(inode); cii = ITOC(inode);
if (coda_isnullfid(&cii->c_fid)) /* we still need to set i_ino for things like stat(2) */
/* new, empty inode found... initializing */ inode->i_ino = hash;
cii->c_fid = *fid; list_add(&cii->c_cilist, &sbi->sbi_cihead);
unlock_new_inode(inode);
/* we shouldnt see inode collisions anymore */ }
if (!coda_fideq(fid, &cii->c_fid)) BUG();
/* always replace the attributes, type might have changed */ /* always replace the attributes, type might have changed */
coda_fill_inode(inode, attr); coda_fill_inode(inode, attr);
...@@ -112,6 +125,7 @@ void coda_replace_fid(struct inode *inode, struct ViceFid *oldfid, ...@@ -112,6 +125,7 @@ void coda_replace_fid(struct inode *inode, struct ViceFid *oldfid,
struct ViceFid *newfid) struct ViceFid *newfid)
{ {
struct coda_inode_info *cii; struct coda_inode_info *cii;
unsigned long hash = coda_f2i(newfid);
cii = ITOC(inode); cii = ITOC(inode);
...@@ -122,60 +136,46 @@ void coda_replace_fid(struct inode *inode, struct ViceFid *oldfid, ...@@ -122,60 +136,46 @@ void coda_replace_fid(struct inode *inode, struct ViceFid *oldfid,
/* XXX we probably need to hold some lock here! */ /* XXX we probably need to hold some lock here! */
remove_inode_hash(inode); remove_inode_hash(inode);
cii->c_fid = *newfid; cii->c_fid = *newfid;
inode->i_ino = coda_f2i(newfid); inode->i_ino = hash;
insert_inode_hash(inode); __insert_inode_hash(inode, hash);
} }
/* convert a fid to an inode. */ /* convert a fid to an inode. */
struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb) struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb)
{ {
ino_t nr;
struct inode *inode; struct inode *inode;
struct coda_inode_info *cii; unsigned long hash = coda_f2i(fid);
if ( !sb ) { if ( !sb ) {
printk("coda_fid_to_inode: no sb!\n"); printk("coda_fid_to_inode: no sb!\n");
return NULL; return NULL;
} }
nr = coda_f2i(fid); inode = iget5_locked(sb, hash, coda_test_inode, coda_fail_inode, fid);
inode = iget4(sb, nr, coda_inocmp, fid); if ( !inode )
if ( !inode ) {
printk("coda_fid_to_inode: null from iget, sb %p, nr %ld.\n",
sb, (long)nr);
return NULL; return NULL;
}
cii = ITOC(inode); /* we should never see newly created inodes because we intentionally
* fail in the initialization callback */
BUG_ON(inode->i_state & I_NEW);
/* The inode could already be purged due to memory pressure */ return inode;
if (coda_isnullfid(&cii->c_fid)) {
inode->i_nlink = 0;
iput(inode);
return NULL;
}
/* we shouldn't see inode collisions anymore */
if ( !coda_fideq(fid, &cii->c_fid) ) BUG();
return inode;
} }
/* the CONTROL inode is made without asking attributes from Venus */ /* the CONTROL inode is made without asking attributes from Venus */
int coda_cnode_makectl(struct inode **inode, struct super_block *sb) int coda_cnode_makectl(struct inode **inode, struct super_block *sb)
{ {
int error = 0; int error = -ENOMEM;
*inode = iget(sb, CTL_INO); *inode = new_inode(sb);
if ( *inode ) { if (*inode) {
(*inode)->i_op = &coda_ioctl_inode_operations; (*inode)->i_ino = CTL_INO;
(*inode)->i_fop = &coda_ioctl_operations; (*inode)->i_op = &coda_ioctl_inode_operations;
(*inode)->i_mode = 0444; (*inode)->i_fop = &coda_ioctl_operations;
error = 0; (*inode)->i_mode = 0444;
} else { error = 0;
error = -ENOMEM; }
}
return error;
return error;
} }
...@@ -33,7 +33,6 @@ ...@@ -33,7 +33,6 @@
#include <linux/coda_cache.h> #include <linux/coda_cache.h>
/* VFS super_block ops */ /* VFS super_block ops */
static void coda_read_inode(struct inode *);
static void coda_clear_inode(struct inode *); static void coda_clear_inode(struct inode *);
static void coda_put_super(struct super_block *); static void coda_put_super(struct super_block *);
static int coda_statfs(struct super_block *sb, struct statfs *buf); static int coda_statfs(struct super_block *sb, struct statfs *buf);
...@@ -92,7 +91,6 @@ struct super_operations coda_super_operations = ...@@ -92,7 +91,6 @@ struct super_operations coda_super_operations =
{ {
alloc_inode: coda_alloc_inode, alloc_inode: coda_alloc_inode,
destroy_inode: coda_destroy_inode, destroy_inode: coda_destroy_inode,
read_inode: coda_read_inode,
clear_inode: coda_clear_inode, clear_inode: coda_clear_inode,
put_super: coda_put_super, put_super: coda_put_super,
statfs: coda_statfs, statfs: coda_statfs,
...@@ -229,18 +227,6 @@ static void coda_put_super(struct super_block *sb) ...@@ -229,18 +227,6 @@ static void coda_put_super(struct super_block *sb)
kfree(sbi); kfree(sbi);
} }
/* all filling in of inodes postponed until lookup */
static void coda_read_inode(struct inode *inode)
{
struct coda_sb_info *sbi = coda_sbp(inode->i_sb);
struct coda_inode_info *cii;
if (!sbi) BUG();
cii = ITOC(inode);
list_add(&cii->c_cilist, &sbi->sbi_cihead);
}
static void coda_clear_inode(struct inode *inode) static void coda_clear_inode(struct inode *inode)
{ {
struct coda_inode_info *cii = ITOC(inode); struct coda_inode_info *cii = ITOC(inode);
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/quotaops.h> #include <linux/quotaops.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/module.h>
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
/* /*
...@@ -443,7 +444,32 @@ int shrink_icache_memory(int priority, int gfp_mask) ...@@ -443,7 +444,32 @@ int shrink_icache_memory(int priority, int gfp_mask)
* by hand after calling find_inode now! This simplifies iunique and won't * by hand after calling find_inode now! This simplifies iunique and won't
* add any additional branch in the common code. * add any additional branch in the common code.
*/ */
static struct inode * find_inode(struct super_block * sb, unsigned long ino, struct list_head *head, find_inode_t find_actor, void *opaque) static struct inode * find_inode(struct super_block * sb, struct list_head *head, int (*test)(struct inode *, void *), void *data)
{
struct list_head *tmp;
struct inode * inode;
tmp = head;
for (;;) {
tmp = tmp->next;
inode = NULL;
if (tmp == head)
break;
inode = list_entry(tmp, struct inode, i_hash);
if (inode->i_sb != sb)
continue;
if (!test(inode, data))
continue;
break;
}
return inode;
}
/*
* find_inode_fast is the fast path version of find_inode, see the comment at
* iget_locked for details.
*/
static struct inode * find_inode_fast(struct super_block * sb, struct list_head *head, unsigned long ino)
{ {
struct list_head *tmp; struct list_head *tmp;
struct inode * inode; struct inode * inode;
...@@ -459,8 +485,6 @@ static struct inode * find_inode(struct super_block * sb, unsigned long ino, str ...@@ -459,8 +485,6 @@ static struct inode * find_inode(struct super_block * sb, unsigned long ino, str
continue; continue;
if (inode->i_sb != sb) if (inode->i_sb != sb)
continue; continue;
if (find_actor && !find_actor(inode, ino, opaque))
continue;
break; break;
} }
return inode; return inode;
...@@ -492,13 +516,28 @@ struct inode *new_inode(struct super_block *sb) ...@@ -492,13 +516,28 @@ struct inode *new_inode(struct super_block *sb)
return inode; return inode;
} }
void unlock_new_inode(struct inode *inode)
{
/*
* This is special! We do not need the spinlock
* when clearing I_LOCK, because we're guaranteed
* that nobody else tries to do anything about the
* state of the inode when it is locked, as we
* just created it (so there can be no old holders
* that haven't tested I_LOCK).
*/
inode->i_state &= ~(I_LOCK|I_NEW);
wake_up(&inode->i_wait);
}
/* /*
* This is called without the inode lock held.. Be careful. * This is called without the inode lock held.. Be careful.
* *
* We no longer cache the sb_flags in i_flags - see fs.h * We no longer cache the sb_flags in i_flags - see fs.h
* -- rmk@arm.uk.linux.org * -- rmk@arm.uk.linux.org
*/ */
static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, struct list_head *head, find_inode_t find_actor, void *opaque) static struct inode * get_new_inode(struct super_block *sb, struct list_head *head, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data)
{ {
struct inode * inode; struct inode * inode;
...@@ -508,37 +547,68 @@ static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, s ...@@ -508,37 +547,68 @@ static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, s
spin_lock(&inode_lock); spin_lock(&inode_lock);
/* We released the lock, so.. */ /* We released the lock, so.. */
old = find_inode(sb, ino, head, find_actor, opaque); old = find_inode(sb, head, test, data);
if (!old) { if (!old) {
if (set(inode, data))
goto set_failed;
inodes_stat.nr_inodes++; inodes_stat.nr_inodes++;
list_add(&inode->i_list, &inode_in_use); list_add(&inode->i_list, &inode_in_use);
list_add(&inode->i_hash, head); list_add(&inode->i_hash, head);
inode->i_ino = ino; inode->i_state = I_LOCK|I_NEW;
inode->i_state = I_LOCK;
spin_unlock(&inode_lock); spin_unlock(&inode_lock);
/* reiserfs specific hack right here. We don't /* Return the locked inode with I_NEW set, the
** want this to last, and are looking for VFS changes * caller is responsible for filling in the contents
** that will allow us to get rid of it.
** -- mason@suse.com
*/
if (sb->s_op->read_inode2) {
sb->s_op->read_inode2(inode, opaque) ;
} else {
sb->s_op->read_inode(inode);
}
/*
* This is special! We do not need the spinlock
* when clearing I_LOCK, because we're guaranteed
* that nobody else tries to do anything about the
* state of the inode when it is locked, as we
* just created it (so there can be no old holders
* that haven't tested I_LOCK).
*/ */
inode->i_state &= ~I_LOCK; return inode;
wake_up(&inode->i_wait); }
/*
* Uhhuh, somebody else created the same inode under
* us. Use the old inode instead of the one we just
* allocated.
*/
__iget(old);
spin_unlock(&inode_lock);
destroy_inode(inode);
inode = old;
wait_on_inode(inode);
}
return inode;
set_failed:
spin_unlock(&inode_lock);
destroy_inode(inode);
return NULL;
}
/*
* get_new_inode_fast is the fast path version of get_new_inode, see the
* comment at iget_locked for details.
*/
static struct inode * get_new_inode_fast(struct super_block *sb, struct list_head *head, unsigned long ino)
{
struct inode * inode;
inode = alloc_inode(sb);
if (inode) {
struct inode * old;
spin_lock(&inode_lock);
/* We released the lock, so.. */
old = find_inode_fast(sb, head, ino);
if (!old) {
inode->i_ino = ino;
inodes_stat.nr_inodes++;
list_add(&inode->i_list, &inode_in_use);
list_add(&inode->i_hash, head);
inode->i_state = I_LOCK|I_NEW;
spin_unlock(&inode_lock);
/* Return the locked inode with I_NEW set, the
* caller is responsible for filling in the contents
*/
return inode; return inode;
} }
...@@ -556,9 +626,9 @@ static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, s ...@@ -556,9 +626,9 @@ static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, s
return inode; return inode;
} }
static inline unsigned long hash(struct super_block *sb, unsigned long i_ino) static inline unsigned long hash(struct super_block *sb, unsigned long hashval)
{ {
unsigned long tmp = i_ino + ((unsigned long) sb / L1_CACHE_BYTES); unsigned long tmp = hashval + ((unsigned long) sb / L1_CACHE_BYTES);
tmp = tmp + (tmp >> I_HASHBITS); tmp = tmp + (tmp >> I_HASHBITS);
return tmp & I_HASHMASK; return tmp & I_HASHMASK;
} }
...@@ -590,7 +660,8 @@ ino_t iunique(struct super_block *sb, ino_t max_reserved) ...@@ -590,7 +660,8 @@ ino_t iunique(struct super_block *sb, ino_t max_reserved)
retry: retry:
if (counter > max_reserved) { if (counter > max_reserved) {
head = inode_hashtable + hash(sb,counter); head = inode_hashtable + hash(sb,counter);
inode = find_inode(sb, res = counter++, head, NULL, NULL); res = counter++;
inode = find_inode_fast(sb, head, res);
if (!inode) { if (!inode) {
spin_unlock(&inode_lock); spin_unlock(&inode_lock);
return res; return res;
...@@ -618,14 +689,18 @@ struct inode *igrab(struct inode *inode) ...@@ -618,14 +689,18 @@ struct inode *igrab(struct inode *inode)
return inode; return inode;
} }
/*
struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque) * This is iget without the read_inode portion of get_new_inode
* the filesystem gets back a new locked and hashed inode and gets
* to fill it in before unlocking it via unlock_new_inode().
*/
struct inode *iget5_locked(struct super_block *sb, unsigned long hashval, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data)
{ {
struct list_head * head = inode_hashtable + hash(sb,ino); struct list_head * head = inode_hashtable + hash(sb, hashval);
struct inode * inode; struct inode * inode;
spin_lock(&inode_lock); spin_lock(&inode_lock);
inode = find_inode(sb, ino, head, find_actor, opaque); inode = find_inode(sb, head, test, data);
if (inode) { if (inode) {
__iget(inode); __iget(inode);
spin_unlock(&inode_lock); spin_unlock(&inode_lock);
...@@ -638,22 +713,57 @@ struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find ...@@ -638,22 +713,57 @@ struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find
* get_new_inode() will do the right thing, re-trying the search * get_new_inode() will do the right thing, re-trying the search
* in case it had to block at any point. * in case it had to block at any point.
*/ */
return get_new_inode(sb, ino, head, find_actor, opaque); return get_new_inode(sb, head, test, set, data);
} }
/*
* Because most filesystems are based on 32-bit unique inode numbers some
* functions are duplicated to keep iget_locked as a fast path. We can avoid
* unnecessary pointer dereferences and function calls for this specific
* case. The duplicated functions (find_inode_fast and get_new_inode_fast)
* have the same pre- and post-conditions as their original counterparts.
*/
struct inode *iget_locked(struct super_block *sb, unsigned long ino)
{
struct list_head * head = inode_hashtable + hash(sb, ino);
struct inode * inode;
spin_lock(&inode_lock);
inode = find_inode_fast(sb, head, ino);
if (inode) {
__iget(inode);
spin_unlock(&inode_lock);
wait_on_inode(inode);
return inode;
}
spin_unlock(&inode_lock);
/*
* get_new_inode_fast() will do the right thing, re-trying the search
* in case it had to block at any point.
*/
return get_new_inode_fast(sb, head, ino);
}
EXPORT_SYMBOL(iget5_locked);
EXPORT_SYMBOL(iget_locked);
EXPORT_SYMBOL(unlock_new_inode);
/** /**
* insert_inode_hash - hash an inode * __insert_inode_hash - hash an inode
* @inode: unhashed inode * @inode: unhashed inode
* @hashval: unsigned long value used to locate this object in the
* inode_hashtable.
* *
* Add an inode to the inode hash for this superblock. If the inode * Add an inode to the inode hash for this superblock. If the inode
* has no superblock it is added to a separate anonymous chain. * has no superblock it is added to a separate anonymous chain.
*/ */
void insert_inode_hash(struct inode *inode) void __insert_inode_hash(struct inode *inode, unsigned long hashval)
{ {
struct list_head *head = &anon_hash_chain; struct list_head *head = &anon_hash_chain;
if (inode->i_sb) if (inode->i_sb)
head = inode_hashtable + hash(inode->i_sb, inode->i_ino); head = inode_hashtable + hash(inode->i_sb, hashval);
spin_lock(&inode_lock); spin_lock(&inode_lock);
list_add(&inode->i_hash, head); list_add(&inode->i_hash, head);
spin_unlock(&inode_lock); spin_unlock(&inode_lock);
......
...@@ -47,7 +47,6 @@ static void nfs_invalidate_inode(struct inode *); ...@@ -47,7 +47,6 @@ static void nfs_invalidate_inode(struct inode *);
static struct inode *nfs_alloc_inode(struct super_block *sb); static struct inode *nfs_alloc_inode(struct super_block *sb);
static void nfs_destroy_inode(struct inode *); static void nfs_destroy_inode(struct inode *);
static void nfs_read_inode(struct inode *);
static void nfs_write_inode(struct inode *,int); static void nfs_write_inode(struct inode *,int);
static void nfs_delete_inode(struct inode *); static void nfs_delete_inode(struct inode *);
static void nfs_put_super(struct super_block *); static void nfs_put_super(struct super_block *);
...@@ -59,7 +58,6 @@ static int nfs_show_options(struct seq_file *, struct vfsmount *); ...@@ -59,7 +58,6 @@ static int nfs_show_options(struct seq_file *, struct vfsmount *);
static struct super_operations nfs_sops = { static struct super_operations nfs_sops = {
alloc_inode: nfs_alloc_inode, alloc_inode: nfs_alloc_inode,
destroy_inode: nfs_destroy_inode, destroy_inode: nfs_destroy_inode,
read_inode: nfs_read_inode,
write_inode: nfs_write_inode, write_inode: nfs_write_inode,
delete_inode: nfs_delete_inode, delete_inode: nfs_delete_inode,
put_super: nfs_put_super, put_super: nfs_put_super,
...@@ -98,15 +96,6 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr) ...@@ -98,15 +96,6 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr)
return nfs_fileid_to_ino_t(fattr->fileid); return nfs_fileid_to_ino_t(fattr->fileid);
} }
/*
* The "read_inode" function doesn't actually do anything:
* the real data is filled in later in nfs_fhget.
*/
static void
nfs_read_inode(struct inode * inode)
{
}
static void static void
nfs_write_inode(struct inode *inode, int sync) nfs_write_inode(struct inode *inode, int sync)
{ {
...@@ -592,7 +581,7 @@ struct nfs_find_desc { ...@@ -592,7 +581,7 @@ struct nfs_find_desc {
* i_ino. * i_ino.
*/ */
static int static int
nfs_find_actor(struct inode *inode, unsigned long ino, void *opaque) nfs_find_actor(struct inode *inode, void *opaque)
{ {
struct nfs_find_desc *desc = (struct nfs_find_desc *)opaque; struct nfs_find_desc *desc = (struct nfs_find_desc *)opaque;
struct nfs_fh *fh = desc->fh; struct nfs_fh *fh = desc->fh;
...@@ -610,6 +599,18 @@ nfs_find_actor(struct inode *inode, unsigned long ino, void *opaque) ...@@ -610,6 +599,18 @@ nfs_find_actor(struct inode *inode, unsigned long ino, void *opaque)
return 1; return 1;
} }
static int
nfs_init_locked(struct inode *inode, void *opaque)
{
struct nfs_find_desc *desc = (struct nfs_find_desc *)opaque;
struct nfs_fh *fh = desc->fh;
struct nfs_fattr *fattr = desc->fattr;
NFS_FILEID(inode) = fattr->fileid;
memcpy(NFS_FH(inode), fh, sizeof(struct nfs_fh));
return 0;
}
/* /*
* This is our own version of iget that looks up inodes by file handle * This is our own version of iget that looks up inodes by file handle
* instead of inode number. We use this technique instead of using * instead of inode number. We use this technique instead of using
...@@ -640,7 +641,7 @@ __nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) ...@@ -640,7 +641,7 @@ __nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
fattr: fattr fattr: fattr
}; };
struct inode *inode = NULL; struct inode *inode = NULL;
unsigned long ino; unsigned long hash;
if ((fattr->valid & NFS_ATTR_FATTR) == 0) if ((fattr->valid & NFS_ATTR_FATTR) == 0)
goto out_no_inode; goto out_no_inode;
...@@ -650,20 +651,21 @@ __nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) ...@@ -650,20 +651,21 @@ __nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
goto out_no_inode; goto out_no_inode;
} }
ino = nfs_fattr_to_ino_t(fattr); hash = nfs_fattr_to_ino_t(fattr);
if (!(inode = iget4(sb, ino, nfs_find_actor, &desc))) if (!(inode = iget5_locked(sb, hash, nfs_find_actor, nfs_init_locked, &desc)))
goto out_no_inode; goto out_no_inode;
if (NFS_NEW(inode)) { if (inode->i_state & I_NEW) {
__u64 new_size, new_mtime; __u64 new_size, new_mtime;
loff_t new_isize; loff_t new_isize;
time_t new_atime; time_t new_atime;
/* We set i_ino for the few things that still rely on it,
* such as stat(2) */
inode->i_ino = hash;
/* We can't support UPDATE_ATIME(), since the server will reset it */ /* We can't support UPDATE_ATIME(), since the server will reset it */
NFS_FLAGS(inode) &= ~NFS_INO_NEW;
NFS_FILEID(inode) = fattr->fileid;
memcpy(NFS_FH(inode), fh, sizeof(struct nfs_fh));
inode->i_flags |= S_NOATIME; inode->i_flags |= S_NOATIME;
inode->i_mode = fattr->mode; inode->i_mode = fattr->mode;
/* Why so? Because we want revalidate for devices/FIFOs, and /* Why so? Because we want revalidate for devices/FIFOs, and
...@@ -711,6 +713,8 @@ __nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) ...@@ -711,6 +713,8 @@ __nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode); NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
NFS_ATTRTIMEO_UPDATE(inode) = jiffies; NFS_ATTRTIMEO_UPDATE(inode) = jiffies;
memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
unlock_new_inode(inode);
} else } else
nfs_refresh_inode(inode, fattr); nfs_refresh_inode(inode, fattr);
dprintk("NFS: __nfs_fhget(%s/%Ld ct=%d)\n", dprintk("NFS: __nfs_fhget(%s/%Ld ct=%d)\n",
...@@ -1231,7 +1235,7 @@ static struct inode *nfs_alloc_inode(struct super_block *sb) ...@@ -1231,7 +1235,7 @@ static struct inode *nfs_alloc_inode(struct super_block *sb)
nfsi = (struct nfs_inode *)kmem_cache_alloc(nfs_inode_cachep, SLAB_KERNEL); nfsi = (struct nfs_inode *)kmem_cache_alloc(nfs_inode_cachep, SLAB_KERNEL);
if (!nfsi) if (!nfsi)
return NULL; return NULL;
nfsi->flags = NFS_INO_NEW; nfsi->flags = 0;
nfsi->mm_cred = NULL; nfsi->mm_cred = NULL;
return &nfsi->vfs_inode; return &nfsi->vfs_inode;
} }
......
...@@ -33,7 +33,7 @@ void reiserfs_delete_inode (struct inode * inode) ...@@ -33,7 +33,7 @@ void reiserfs_delete_inode (struct inode * inode)
lock_kernel() ; lock_kernel() ;
/* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */ /* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */
if (INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */ if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */
down (&inode->i_sem); down (&inode->i_sem);
journal_begin(&th, inode->i_sb, jbegin_count) ; journal_begin(&th, inode->i_sb, jbegin_count) ;
...@@ -886,7 +886,7 @@ int reiserfs_get_block (struct inode * inode, sector_t block, ...@@ -886,7 +886,7 @@ int reiserfs_get_block (struct inode * inode, sector_t block,
// item version directly // item version directly
// //
// called by read_inode // called by read_locked_inode
static void init_inode (struct inode * inode, struct path * path) static void init_inode (struct inode * inode, struct path * path)
{ {
struct buffer_head * bh; struct buffer_head * bh;
...@@ -1117,7 +1117,7 @@ void reiserfs_update_sd (struct reiserfs_transaction_handle *th, ...@@ -1117,7 +1117,7 @@ void reiserfs_update_sd (struct reiserfs_transaction_handle *th,
return; return;
} }
/* reiserfs_read_inode2 is called to read the inode off disk, and it /* reiserfs_read_locked_inode is called to read the inode off disk, and it
** does a make_bad_inode when things go wrong. But, we need to make sure ** does a make_bad_inode when things go wrong. But, we need to make sure
** and clear the key in the private portion of the inode, otherwise a ** and clear the key in the private portion of the inode, otherwise a
** corresponding iput might try to delete whatever object the inode last ** corresponding iput might try to delete whatever object the inode last
...@@ -1128,32 +1128,29 @@ static void reiserfs_make_bad_inode(struct inode *inode) { ...@@ -1128,32 +1128,29 @@ static void reiserfs_make_bad_inode(struct inode *inode) {
make_bad_inode(inode); make_bad_inode(inode);
} }
void reiserfs_read_inode(struct inode *inode) {
reiserfs_make_bad_inode(inode) ;
}
// //
// initially this function was derived from minix or ext2's analog and // initially this function was derived from minix or ext2's analog and
// evolved as the prototype did // evolved as the prototype did
// //
int reiserfs_init_locked_inode (struct inode * inode, void *p)
{
struct reiserfs_iget_args *args = (struct reiserfs_iget_args *)p ;
inode->i_ino = args->objectid;
INODE_PKEY(inode)->k_dir_id = cpu_to_le32(args->dirid);
return 0;
}
/* looks for stat data in the tree, and fills up the fields of in-core /* looks for stat data in the tree, and fills up the fields of in-core
inode stat data fields */ inode stat data fields */
void reiserfs_read_inode2 (struct inode * inode, void *p) void reiserfs_read_locked_inode (struct inode * inode, struct reiserfs_iget_args *args)
{ {
INITIALIZE_PATH (path_to_sd); INITIALIZE_PATH (path_to_sd);
struct cpu_key key; struct cpu_key key;
struct reiserfs_iget4_args *args = (struct reiserfs_iget4_args *)p ;
unsigned long dirino; unsigned long dirino;
int retval; int retval;
if (!p) { dirino = args->dirid ;
reiserfs_make_bad_inode(inode) ;
return;
}
dirino = args->objectid ;
/* set version 1, version 2 could be used too, because stat data /* set version 1, version 2 could be used too, because stat data
key is the same in both versions */ key is the same in both versions */
...@@ -1166,7 +1163,7 @@ void reiserfs_read_inode2 (struct inode * inode, void *p) ...@@ -1166,7 +1163,7 @@ void reiserfs_read_inode2 (struct inode * inode, void *p)
/* look for the object's stat data */ /* look for the object's stat data */
retval = search_item (inode->i_sb, &key, &path_to_sd); retval = search_item (inode->i_sb, &key, &path_to_sd);
if (retval == IO_ERROR) { if (retval == IO_ERROR) {
reiserfs_warning ("vs-13070: reiserfs_read_inode2: " reiserfs_warning ("vs-13070: reiserfs_read_locked_inode: "
"i/o failure occurred trying to find stat data of %K\n", "i/o failure occurred trying to find stat data of %K\n",
&key); &key);
reiserfs_make_bad_inode(inode) ; reiserfs_make_bad_inode(inode) ;
...@@ -1198,7 +1195,7 @@ void reiserfs_read_inode2 (struct inode * inode, void *p) ...@@ -1198,7 +1195,7 @@ void reiserfs_read_inode2 (struct inode * inode, void *p)
during mount (fs/reiserfs/super.c:finish_unfinished()). */ during mount (fs/reiserfs/super.c:finish_unfinished()). */
if( ( inode -> i_nlink == 0 ) && if( ( inode -> i_nlink == 0 ) &&
! REISERFS_SB(inode -> i_sb) -> s_is_unlinked_ok ) { ! REISERFS_SB(inode -> i_sb) -> s_is_unlinked_ok ) {
reiserfs_warning( "vs-13075: reiserfs_read_inode2: " reiserfs_warning( "vs-13075: reiserfs_read_locked_inode: "
"dead inode read from disk %K. " "dead inode read from disk %K. "
"This is likely to be race with knfsd. Ignore\n", "This is likely to be race with knfsd. Ignore\n",
&key ); &key );
...@@ -1210,39 +1207,44 @@ void reiserfs_read_inode2 (struct inode * inode, void *p) ...@@ -1210,39 +1207,44 @@ void reiserfs_read_inode2 (struct inode * inode, void *p)
} }
/** /**
* reiserfs_find_actor() - "find actor" reiserfs supplies to iget4(). * reiserfs_find_actor() - "find actor" reiserfs supplies to iget5_locked().
* *
* @inode: inode from hash table to check * @inode: inode from hash table to check
* @inode_no: inode number we are looking for * @opaque: "cookie" passed to iget5_locked(). This is &reiserfs_iget_args.
* @opaque: "cookie" passed to iget4(). This is &reiserfs_iget4_args.
* *
* This function is called by iget4() to distinguish reiserfs inodes * This function is called by iget5_locked() to distinguish reiserfs inodes
* having the same inode numbers. Such inodes can only exist due to some * having the same inode numbers. Such inodes can only exist due to some
* error condition. One of them should be bad. Inodes with identical * error condition. One of them should be bad. Inodes with identical
* inode numbers (objectids) are distinguished by parent directory ids. * inode numbers (objectids) are distinguished by parent directory ids.
* *
*/ */
static int reiserfs_find_actor( struct inode *inode, int reiserfs_find_actor( struct inode *inode, void *opaque )
unsigned long inode_no, void *opaque )
{ {
struct reiserfs_iget4_args *args; struct reiserfs_iget_args *args;
args = opaque; args = opaque;
/* args is already in CPU order */ /* args is already in CPU order */
return le32_to_cpu(INODE_PKEY(inode)->k_dir_id) == args -> objectid; return (inode->i_ino == args->objectid) &&
(le32_to_cpu(INODE_PKEY(inode)->k_dir_id) == args->dirid);
} }
struct inode * reiserfs_iget (struct super_block * s, const struct cpu_key * key) struct inode * reiserfs_iget (struct super_block * s, const struct cpu_key * key)
{ {
struct inode * inode; struct inode * inode;
struct reiserfs_iget4_args args ; struct reiserfs_iget_args args ;
args.objectid = key->on_disk_key.k_dir_id ; args.objectid = key->on_disk_key.k_objectid ;
inode = iget4 (s, key->on_disk_key.k_objectid, args.dirid = key->on_disk_key.k_dir_id ;
reiserfs_find_actor, (void *)(&args)); inode = iget5_locked (s, key->on_disk_key.k_objectid,
reiserfs_find_actor, reiserfs_init_locked_inode, (void *)(&args));
if (!inode) if (!inode)
return ERR_PTR(-ENOMEM) ; return ERR_PTR(-ENOMEM) ;
if (inode->i_state & I_NEW) {
reiserfs_read_locked_inode(inode, &args);
unlock_new_inode(inode);
}
if (comp_short_keys (INODE_PKEY (inode), key) || is_bad_inode (inode)) { if (comp_short_keys (INODE_PKEY (inode), key) || is_bad_inode (inode)) {
/* either due to i/o error or a stale NFS handle */ /* either due to i/o error or a stale NFS handle */
iput (inode); iput (inode);
......
...@@ -484,8 +484,6 @@ struct super_operations reiserfs_sops = ...@@ -484,8 +484,6 @@ struct super_operations reiserfs_sops =
{ {
alloc_inode: reiserfs_alloc_inode, alloc_inode: reiserfs_alloc_inode,
destroy_inode: reiserfs_destroy_inode, destroy_inode: reiserfs_destroy_inode,
read_inode: reiserfs_read_inode,
read_inode2: reiserfs_read_inode2,
write_inode: reiserfs_write_inode, write_inode: reiserfs_write_inode,
dirty_inode: reiserfs_dirty_inode, dirty_inode: reiserfs_dirty_inode,
delete_inode: reiserfs_delete_inode, delete_inode: reiserfs_delete_inode,
...@@ -1007,7 +1005,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) ...@@ -1007,7 +1005,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
int old_format = 0; int old_format = 0;
unsigned long blocks; unsigned long blocks;
int jinit_done = 0 ; int jinit_done = 0 ;
struct reiserfs_iget4_args args ; struct reiserfs_iget_args args ;
struct reiserfs_super_block * rs; struct reiserfs_super_block * rs;
char *jdev_name; char *jdev_name;
struct reiserfs_sb_info *sbi; struct reiserfs_sb_info *sbi;
...@@ -1069,13 +1067,19 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) ...@@ -1069,13 +1067,19 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
printk("clm-7000: Detected readonly device, marking FS readonly\n") ; printk("clm-7000: Detected readonly device, marking FS readonly\n") ;
s->s_flags |= MS_RDONLY ; s->s_flags |= MS_RDONLY ;
} }
args.objectid = REISERFS_ROOT_PARENT_OBJECTID ; args.objectid = REISERFS_ROOT_OBJECTID ;
root_inode = iget4 (s, REISERFS_ROOT_OBJECTID, 0, (void *)(&args)); args.dirid = REISERFS_ROOT_PARENT_OBJECTID ;
root_inode = iget5_locked (s, REISERFS_ROOT_OBJECTID, reiserfs_find_actor, reiserfs_init_locked_inode, (void *)(&args));
if (!root_inode) { if (!root_inode) {
printk ("reiserfs_fill_super: get root inode failed\n"); printk ("reiserfs_fill_super: get root inode failed\n");
goto error; goto error;
} }
if (root_inode->i_state & I_NEW) {
reiserfs_read_locked_inode(root_inode, &args);
unlock_new_inode(root_inode);
}
s->s_root = d_alloc_root(root_inode); s->s_root = d_alloc_root(root_inode);
if (!s->s_root) { if (!s->s_root) {
iput(root_inode); iput(root_inode);
......
...@@ -771,13 +771,6 @@ struct super_operations { ...@@ -771,13 +771,6 @@ struct super_operations {
void (*read_inode) (struct inode *); void (*read_inode) (struct inode *);
/* reiserfs kludge. reiserfs needs 64 bits of information to
** find an inode. We are using the read_inode2 call to get
** that information. We don't like this, and are waiting on some
** VFS changes for the real solution.
** iget4 calls read_inode2, iff it is defined
*/
void (*read_inode2) (struct inode *, void *) ;
void (*dirty_inode) (struct inode *); void (*dirty_inode) (struct inode *);
void (*write_inode) (struct inode *, int); void (*write_inode) (struct inode *, int);
void (*put_inode) (struct inode *); void (*put_inode) (struct inode *);
...@@ -801,6 +794,7 @@ struct super_operations { ...@@ -801,6 +794,7 @@ struct super_operations {
#define I_LOCK 8 #define I_LOCK 8
#define I_FREEING 16 #define I_FREEING 16
#define I_CLEAR 32 #define I_CLEAR 32
#define I_NEW 64
#define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES) #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES)
...@@ -1208,19 +1202,33 @@ extern void force_delete(struct inode *); ...@@ -1208,19 +1202,33 @@ extern void force_delete(struct inode *);
extern struct inode * igrab(struct inode *); extern struct inode * igrab(struct inode *);
extern ino_t iunique(struct super_block *, ino_t); extern ino_t iunique(struct super_block *, ino_t);
typedef int (*find_inode_t)(struct inode *, unsigned long, void *); extern struct inode * iget5_locked(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *);
extern struct inode * iget4(struct super_block *, unsigned long, find_inode_t, void *); extern struct inode * iget_locked(struct super_block *, unsigned long);
extern void unlock_new_inode(struct inode *);
static inline struct inode *iget(struct super_block *sb, unsigned long ino) static inline struct inode *iget(struct super_block *sb, unsigned long ino)
{ {
return iget4(sb, ino, NULL, NULL); struct inode *inode = iget_locked(sb, ino);
if (inode && (inode->i_state & I_NEW)) {
sb->s_op->read_inode(inode);
unlock_new_inode(inode);
}
return inode;
} }
extern void __iget(struct inode * inode); extern void __iget(struct inode * inode);
extern void clear_inode(struct inode *); extern void clear_inode(struct inode *);
extern struct inode *new_inode(struct super_block *); extern struct inode *new_inode(struct super_block *);
extern void remove_suid(struct dentry *); extern void remove_suid(struct dentry *);
extern void insert_inode_hash(struct inode *);
extern void __insert_inode_hash(struct inode *, unsigned long hashval);
extern void remove_inode_hash(struct inode *); extern void remove_inode_hash(struct inode *);
static inline void insert_inode_hash(struct inode *inode) {
__insert_inode_hash(inode, inode->i_ino);
}
extern struct file * get_empty_filp(void); extern struct file * get_empty_filp(void);
extern void file_move(struct file *f, struct list_head *list); extern void file_move(struct file *f, struct list_head *list);
extern void ll_rw_block(int, int, struct buffer_head * bh[]); extern void ll_rw_block(int, int, struct buffer_head * bh[]);
......
...@@ -170,7 +170,6 @@ struct nfs_inode { ...@@ -170,7 +170,6 @@ struct nfs_inode {
#define NFS_INO_REVALIDATING 0x0004 /* revalidating attrs */ #define NFS_INO_REVALIDATING 0x0004 /* revalidating attrs */
#define NFS_IS_SNAPSHOT 0x0010 /* a snapshot file */ #define NFS_IS_SNAPSHOT 0x0010 /* a snapshot file */
#define NFS_INO_FLUSH 0x0020 /* inode is due for flushing */ #define NFS_INO_FLUSH 0x0020 /* inode is due for flushing */
#define NFS_INO_NEW 0x0040 /* hadn't been filled yet */
static inline struct nfs_inode *NFS_I(struct inode *inode) static inline struct nfs_inode *NFS_I(struct inode *inode)
{ {
...@@ -208,7 +207,6 @@ do { \ ...@@ -208,7 +207,6 @@ do { \
#define NFS_FLAGS(inode) (NFS_I(inode)->flags) #define NFS_FLAGS(inode) (NFS_I(inode)->flags)
#define NFS_REVALIDATING(inode) (NFS_FLAGS(inode) & NFS_INO_REVALIDATING) #define NFS_REVALIDATING(inode) (NFS_FLAGS(inode) & NFS_INO_REVALIDATING)
#define NFS_STALE(inode) (NFS_FLAGS(inode) & NFS_INO_STALE) #define NFS_STALE(inode) (NFS_FLAGS(inode) & NFS_INO_STALE)
#define NFS_NEW(inode) (NFS_FLAGS(inode) & NFS_INO_NEW)
#define NFS_FILEID(inode) (NFS_I(inode)->fileid) #define NFS_FILEID(inode) (NFS_I(inode)->fileid)
......
...@@ -1564,8 +1564,9 @@ extern struct item_operations * item_ops [TYPE_ANY + 1]; ...@@ -1564,8 +1564,9 @@ extern struct item_operations * item_ops [TYPE_ANY + 1];
#define B_I_POS_UNFM_POINTER(bh,ih,pos) le32_to_cpu(*(((unp_t *)B_I_PITEM(bh,ih)) + (pos))) #define B_I_POS_UNFM_POINTER(bh,ih,pos) le32_to_cpu(*(((unp_t *)B_I_PITEM(bh,ih)) + (pos)))
#define PUT_B_I_POS_UNFM_POINTER(bh,ih,pos, val) do {*(((unp_t *)B_I_PITEM(bh,ih)) + (pos)) = cpu_to_le32(val); } while (0) #define PUT_B_I_POS_UNFM_POINTER(bh,ih,pos, val) do {*(((unp_t *)B_I_PITEM(bh,ih)) + (pos)) = cpu_to_le32(val); } while (0)
struct reiserfs_iget4_args { struct reiserfs_iget_args {
__u32 objectid ; __u32 objectid ;
__u32 dirid ;
} ; } ;
/***************************************************************************/ /***************************************************************************/
...@@ -1818,8 +1819,9 @@ void padd_item (char * item, int total_length, int length); ...@@ -1818,8 +1819,9 @@ void padd_item (char * item, int total_length, int length);
/* inode.c */ /* inode.c */
void reiserfs_read_inode (struct inode * inode) ; void reiserfs_read_locked_inode(struct inode * inode, struct reiserfs_iget_args *args) ;
void reiserfs_read_inode2(struct inode * inode, void *p) ; int reiserfs_find_actor(struct inode * inode, void *p) ;
int reiserfs_init_locked_inode(struct inode * inode, void *p) ;
void reiserfs_delete_inode (struct inode * inode); void reiserfs_delete_inode (struct inode * inode);
void reiserfs_write_inode (struct inode * inode, int) ; void reiserfs_write_inode (struct inode * inode, int) ;
struct dentry *reiserfs_get_dentry(struct super_block *, void *) ; struct dentry *reiserfs_get_dentry(struct super_block *, void *) ;
......
...@@ -137,7 +137,6 @@ EXPORT_SYMBOL(fput); ...@@ -137,7 +137,6 @@ EXPORT_SYMBOL(fput);
EXPORT_SYMBOL(fget); EXPORT_SYMBOL(fget);
EXPORT_SYMBOL(igrab); EXPORT_SYMBOL(igrab);
EXPORT_SYMBOL(iunique); EXPORT_SYMBOL(iunique);
EXPORT_SYMBOL(iget4);
EXPORT_SYMBOL(iput); EXPORT_SYMBOL(iput);
EXPORT_SYMBOL(inode_init_once); EXPORT_SYMBOL(inode_init_once);
EXPORT_SYMBOL(force_delete); EXPORT_SYMBOL(force_delete);
...@@ -540,7 +539,7 @@ EXPORT_SYMBOL(clear_inode); ...@@ -540,7 +539,7 @@ EXPORT_SYMBOL(clear_inode);
EXPORT_SYMBOL(init_special_inode); EXPORT_SYMBOL(init_special_inode);
EXPORT_SYMBOL(__get_hash_table); EXPORT_SYMBOL(__get_hash_table);
EXPORT_SYMBOL(new_inode); EXPORT_SYMBOL(new_inode);
EXPORT_SYMBOL(insert_inode_hash); EXPORT_SYMBOL(__insert_inode_hash);
EXPORT_SYMBOL(remove_inode_hash); EXPORT_SYMBOL(remove_inode_hash);
EXPORT_SYMBOL(buffer_insert_list); EXPORT_SYMBOL(buffer_insert_list);
EXPORT_SYMBOL(make_bad_inode); EXPORT_SYMBOL(make_bad_inode);
......
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