Commit 5770cca7 authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.78pre1

parent c7c53f5b
DE10x
=====
Memory Addresses:
SW1 SW2 SW3 SW4
64K on on on on d0000 dbfff
off on on on c0000 cbfff
off off on on e0000 ebfff
32K on on off on d8000 dbfff
off on off on c8000 cbfff
off off off on e8000 ebfff
DBR ROM on on dc000 dffff
off on cc000 cffff
off off ec000 effff
Note that the 2K mode is set by SW3/SW4 on/off or off/off. Address
assignment is through the RBSA register.
I/O Address:
SW5
0x300 on
0x200 off
Remote Boot:
SW6
Disable on
Enable off
Remote Boot Timeout:
SW7
2.5min on
30s off
IRQ:
SW8 SW9 SW10 SW11 SW12
2 on off off off off
3 off on off off off
4 off off on off off
5 off off off on off
7 off off off off on
DE20x
=====
Memory Size:
SW3 SW4
64K on on
32K off on
2K on off
2K off off
Start Addresses:
SW1 SW2 SW3 SW4
64K on on on on c0000 cffff
on off on on d0000 dffff
off on on on e0000 effff
32K on on off off c8000 cffff
on off off off d8000 dffff
off on off off e8000 effff
Illegal off off - - - -
I/O Address:
SW5
0x300 on
0x200 off
Remote Boot:
SW6
Disable on
Enable off
Remote Boot Timeout:
SW7
2.5min on
30s off
IRQ:
SW8 SW9 SW10 SW11 SW12
5 on off off off off
9 off on off off off
10 off off on off off
11 off off off on off
15 off off off off on
VERSION = 2
PATCHLEVEL = 1
SUBLEVEL = 77
SUBLEVEL = 78
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
......
......@@ -220,8 +220,9 @@ affs_write_inode(struct inode *inode)
}
int
affs_notify_change(struct inode *inode, struct iattr *attr)
affs_notify_change(struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = dentry->d_inode;
int error;
pr_debug("AFFS: notify_change(%lu,0x%x)\n",inode->i_ino,attr->ia_valid);
......
......@@ -19,8 +19,8 @@
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
static int affs_readlink(struct inode *, char *, int);
static struct dentry *affs_follow_link(struct inode *inode, struct dentry *base);
static int affs_readlink(struct dentry *, char *, int);
static struct dentry *affs_follow_link(struct dentry *dentry, struct dentry *base);
struct inode_operations affs_symlink_inode_operations = {
NULL, /* no file-operations */
......@@ -44,8 +44,9 @@ struct inode_operations affs_symlink_inode_operations = {
};
static int
affs_readlink(struct inode *inode, char *buffer, int buflen)
affs_readlink(struct inode *dentry, char *buffer, int buflen)
{
struct inode *inode = dentry->d_inode;
struct buffer_head *bh;
struct slink_front *lf;
int i, j;
......@@ -97,8 +98,9 @@ affs_readlink(struct inode *inode, char *buffer, int buflen)
}
static struct dentry *
affs_follow_link(struct inode *inode, struct dentry *base)
affs_follow_link(struct dentry *dentry, struct dentry *base)
{
struct inode *inode = dentry->d_inode;
struct buffer_head *bh;
struct slink_front *lf;
char *buffer;
......
......@@ -81,8 +81,9 @@ void inode_setattr(struct inode * inode, struct iattr * attr)
mark_inode_dirty(inode);
}
int notify_change(struct inode * inode, struct iattr * attr)
int notify_change(struct dentry * dentry, struct iattr * attr)
{
struct inode *inode = dentry->d_inode;
int error;
time_t now = CURRENT_TIME;
unsigned int ia_valid = attr->ia_valid;
......@@ -93,11 +94,13 @@ int notify_change(struct inode * inode, struct iattr * attr)
if (!(ia_valid & ATTR_MTIME_SET))
attr->ia_mtime = now;
if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->notify_change)
return inode->i_sb->s_op->notify_change(inode, attr);
if (inode->i_sb && inode->i_sb->s_op &&
inode->i_sb->s_op->notify_change)
error = inode->i_sb->s_op->notify_change(dentry, attr);
else {
error = inode_change_ok(inode, attr);
if (!error)
inode_setattr(inode, attr);
}
return error;
}
......@@ -14,23 +14,24 @@
#include <linux/sched.h>
#include "autofs_i.h"
static int autofs_readlink(struct inode *inode, char *buffer, int buflen)
static int autofs_readlink(struct dentry *dentry, char *buffer, int buflen)
{
struct autofs_symlink *sl;
int len;
sl = (struct autofs_symlink *)inode->u.generic_ip;
sl = (struct autofs_symlink *)dentry->d_inode->u.generic_ip;
len = sl->len;
if (len > buflen) len = buflen;
copy_to_user(buffer,sl->data,len);
copy_to_user(buffer, sl->data, len);
return len;
}
static struct dentry * autofs_follow_link(struct inode *inode, struct dentry *base)
static struct dentry * autofs_follow_link(struct dentry *dentry,
struct dentry *base)
{
struct autofs_symlink *sl;
sl = (struct autofs_symlink *)inode->u.generic_ip;
sl = (struct autofs_symlink *)dentry->d_inode->u.generic_ip;
return lookup_dentry(sl->data, base, 1);
}
......
......@@ -13,7 +13,7 @@
/*
* The follow_symlink operation must dput() the base.
*/
static struct dentry * bad_follow_link(struct inode * ino, struct dentry *base)
static struct dentry * bad_follow_link(struct dentry *dent, struct dentry *base)
{
dput(base);
return ERR_PTR(-EIO);
......
......@@ -1522,8 +1522,9 @@ void mark_buffer_uptodate(struct buffer_head * bh, int on)
* mark_buffer_uptodate() functions propagate buffer state into the
* page struct once IO has completed.
*/
int generic_readpage(struct inode * inode, struct page * page)
int generic_readpage(struct dentry * dentry, struct page * page)
{
struct inode *inode = dentry->d_inode;
unsigned long block;
int *p, nr[PAGE_SIZE/512];
int i;
......
......@@ -25,10 +25,10 @@
#include <linux/coda_cache.h>
/* file operations */
static int coda_readpage(struct inode * inode, struct page * page);
static ssize_t coda_file_read(struct file *f, char *buf, size_t count, loff_t *off);
static ssize_t coda_file_write(struct file *f, const char *buf, size_t count, loff_t *off);
static int coda_file_mmap(struct file * file, struct vm_area_struct * vma);
static int coda_readpage(struct dentry *, struct page *);
static ssize_t coda_file_read(struct file *, char *, size_t, loff_t *);
static ssize_t coda_file_write(struct file *, const char *, size_t, loff_t *);
static int coda_file_mmap(struct file *, struct vm_area_struct *);
/* exported from this file */
int coda_fsync(struct file *, struct dentry *dentry);
......@@ -74,9 +74,9 @@ struct file_operations coda_file_operations = {
};
/* File file operations */
static int coda_readpage(struct inode * inode, struct page * page)
static int coda_readpage(struct dentry *dentry, struct page * page)
{
struct inode *open_inode;
struct inode *open_inode, *inode = dentry->d_inode;
struct cnode *cnp;
ENTRY;
......@@ -93,6 +93,7 @@ static int coda_readpage(struct inode * inode, struct page * page)
CDEBUG(D_INODE, "coda ino: %ld, cached ino %ld, page offset: %lx\n", inode->i_ino, open_inode->i_ino, page->offset);
/* N.B. This needs the dentry for open_inode */
generic_readpage(open_inode, page);
EXIT;
return 0;
......
......@@ -41,7 +41,7 @@
/* VFS super_block ops */
static struct super_block *coda_read_super(struct super_block *, void *, int);
static void coda_read_inode(struct inode *);
static int coda_notify_change(struct inode *inode, struct iattr *attr);
static int coda_notify_change(struct dentry *, struct iattr *);
static void coda_put_inode(struct inode *);
static void coda_delete_inode(struct inode *);
static void coda_put_super(struct super_block *);
......@@ -133,6 +133,7 @@ static struct super_block * coda_read_super(struct super_block *sb,
printk("coda_read_super: rootinode is %ld dev %d\n",
root->i_ino, root->i_dev);
sbi->sbi_root = root;
/* N.B. check this for failure */
sb->s_root = d_alloc_root(root, NULL);
unlock_super(sb);
EXIT;
......@@ -140,7 +141,6 @@ static struct super_block * coda_read_super(struct super_block *sb,
error:
EXIT;
MOD_DEC_USE_COUNT;
if (sbi) {
sbi->sbi_vcomm = NULL;
sbi->sbi_root = NULL;
......@@ -154,6 +154,7 @@ EXIT;
coda_cnode_free(ITOC(root));
}
sb->s_dev = 0;
MOD_DEC_USE_COUNT;
return NULL;
}
......@@ -224,8 +225,9 @@ static void coda_delete_inode(struct inode *inode)
EXIT;
}
static int coda_notify_change(struct inode *inode, struct iattr *iattr)
static int coda_notify_change(struct dentry *dentry, struct iattr *iattr)
{
struct inode *inode = dentry->d_inode;
struct cnode *cnp;
struct coda_vattr vattr;
int error;
......
......@@ -24,8 +24,8 @@
#include <linux/coda_cnode.h>
#include <linux/coda_cache.h>
static int coda_readlink(struct inode *inode, char *buffer, int length);
static struct dentry *coda_follow_link(struct inode *, struct dentry *);
static int coda_readlink(struct dentry *dentry, char *buffer, int length);
static struct dentry *coda_follow_link(struct dentry *, struct dentry *);
struct inode_operations coda_symlink_inode_operations = {
NULL, /* no file-operations */
......@@ -50,8 +50,9 @@ struct inode_operations coda_symlink_inode_operations = {
NULL /* revalidate */
};
static int coda_readlink(struct inode *inode, char *buffer, int length)
static int coda_readlink(struct inode *dentry, char *buffer, int length)
{
struct inode *inode = dentry->d_inode;
int len;
int error;
char *buf;
......@@ -83,14 +84,15 @@ static int coda_readlink(struct inode *inode, char *buffer, int length)
return error;
}
static struct dentry *coda_follow_link(struct inode *inode,
static struct dentry *coda_follow_link(struct dentry *dentry,
struct dentry *base)
{
struct inode *inode = dentry->d_inode;
int error;
struct cnode *cnp;
unsigned int len;
char mem[CFS_MAXPATHLEN];
char *path;
char mem[CFS_MAXPATHLEN]; /* N.B. too big for the stack? */
ENTRY;
CDEBUG(D_INODE, "(%x/%ld)\n", inode->i_dev, inode->i_ino);
......
......@@ -52,6 +52,8 @@ struct {
static inline void d_free(struct dentry *dentry)
{
if (dentry->d_op && dentry->d_op->d_release)
dentry->d_op->d_release(dentry);
kfree(dentry->d_name.name);
kfree(dentry);
}
......@@ -502,6 +504,7 @@ printk("d_alloc: %d unused, pruning dcache\n", dentry_stat.nr_unused);
dentry->d_name.len = name->len;
dentry->d_name.hash = name->hash;
dentry->d_op = NULL;
dentry->d_fsdata = NULL;
return dentry;
}
......
......@@ -631,23 +631,25 @@ int ext2_sync_inode (struct inode *inode)
return ext2_update_inode (inode, 1);
}
int ext2_notify_change(struct inode *inode, struct iattr *iattr)
int ext2_notify_change(struct dentry *dentry, struct iattr *iattr)
{
struct inode *inode = dentry->d_inode;
int retval;
unsigned int flags;
retval = -EPERM;
if ((iattr->ia_attr_flags &
(ATTR_FLAG_APPEND | ATTR_FLAG_IMMUTABLE)) ^
(inode->u.ext2_i.i_flags &
(EXT2_APPEND_FL | EXT2_IMMUTABLE_FL))) {
if (securelevel > 0 || !fsuser())
return -EPERM;
} else
if ((current->fsuid != inode->i_uid) && !fsuser())
return -EPERM;
goto out;
} else if ((current->fsuid != inode->i_uid) && !fsuser())
goto out;
if ((retval = inode_change_ok(inode, iattr)) != 0)
return retval;
retval = inode_change_ok(inode, iattr);
if (retval != 0)
goto out;
inode_setattr(inode, iattr);
......@@ -681,7 +683,7 @@ int ext2_notify_change(struct inode *inode, struct iattr *iattr)
inode->u.ext2_i.i_flags &= ~EXT2_IMMUTABLE_FL;
}
mark_inode_dirty(inode);
return 0;
out:
return retval;
}
......@@ -793,8 +793,10 @@ int ext2_symlink (struct inode * dir, struct dentry *dentry, const char * symnam
goto out;
}
int ext2_link (struct inode * inode, struct inode * dir, struct dentry *dentry)
int ext2_link (struct dentry * old_dentry,
struct inode * dir, struct dentry *dentry)
{
struct inode *inode = old_dentry->d_inode;
struct ext2_dir_entry * de;
struct buffer_head * bh;
int err;
......
......@@ -24,8 +24,8 @@
#include <linux/mm.h>
#include <linux/stat.h>
static int ext2_readlink (struct inode *, char *, int);
static struct dentry *ext2_follow_link(struct inode *, struct dentry *);
static int ext2_readlink (struct dentry *, char *, int);
static struct dentry *ext2_follow_link(struct dentry *, struct dentry *);
/*
* symlinks can't do much...
......@@ -51,10 +51,12 @@ struct inode_operations ext2_symlink_inode_operations = {
NULL /* smap */
};
static struct dentry * ext2_follow_link(struct inode * inode, struct dentry *base)
static struct dentry * ext2_follow_link(struct dentry * dentry,
struct dentry *base)
{
int error;
struct inode *inode = dentry->d_inode;
struct buffer_head * bh = NULL;
int error;
char * link;
link = (char *) inode->u.ext2_i.i_data;
......@@ -72,8 +74,9 @@ static struct dentry * ext2_follow_link(struct inode * inode, struct dentry *bas
return base;
}
static int ext2_readlink (struct inode * inode, char * buffer, int buflen)
static int ext2_readlink (struct dentry * dentry, char * buffer, int buflen)
{
struct inode *inode = dentry->d_inode;
struct buffer_head * bh = NULL;
char * link;
int i;
......
......@@ -783,9 +783,10 @@ void fat_write_inode(struct inode *inode)
}
int fat_notify_change(struct inode * inode,struct iattr * attr)
int fat_notify_change(struct dentry * dentry, struct iattr * attr)
{
struct super_block *sb = inode->i_sb;
struct super_block *sb = dentry->d_sb;
struct inode *inode = dentry->d_inode;
int error;
error = inode_change_ok(inode, attr);
......
......@@ -18,8 +18,8 @@
#include <asm/uaccess.h>
static int isofs_readlink(struct inode *, char *, int);
static struct dentry * isofs_follow_link(struct inode * inode, struct dentry *base);
static int isofs_readlink(struct dentry *, char *, int);
static struct dentry * isofs_follow_link(struct dentry *, struct dentry *);
/*
* symlinks can't do much...
......@@ -44,14 +44,14 @@ struct inode_operations isofs_symlink_inode_operations = {
NULL /* permission */
};
static int isofs_readlink(struct inode * inode, char * buffer, int buflen)
static int isofs_readlink(struct dentry * dentry, char * buffer, int buflen)
{
char * pnt;
int i;
if (buflen > 1023)
buflen = 1023;
pnt = get_rock_ridge_symlink(inode);
pnt = get_rock_ridge_symlink(dentry->d_inode);
if (!pnt)
return 0;
......@@ -65,12 +65,12 @@ static int isofs_readlink(struct inode * inode, char * buffer, int buflen)
return i;
}
static struct dentry * isofs_follow_link(struct inode * inode, struct dentry *base)
static struct dentry * isofs_follow_link(struct dentry * dentry,
struct dentry *base)
{
char * pnt;
pnt = get_rock_ridge_symlink(inode);
pnt = get_rock_ridge_symlink(dentry->d_inode);
if(!pnt) {
dput(base);
return ERR_PTR(-ELOOP);
......
......@@ -42,7 +42,7 @@ nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
memset(argp, 0, sizeof(*argp));
argp->cookie = nlm_cookie++;
argp->state = nsm_local_state;
lock->fh = *NFS_FH(fl->fl_file->f_dentry->d_inode);
lock->fh = *NFS_FH(fl->fl_file->f_dentry);
lock->caller = system_utsname.nodename;
lock->oh.data = req->a_owner;
lock->oh.len = sprintf(req->a_owner, "%d@%s",
......
......@@ -14,8 +14,8 @@
#include <asm/uaccess.h>
static int minix_readlink(struct inode *, char *, int);
static struct dentry *minix_follow_link(struct inode *, struct dentry *);
static int minix_readlink(struct dentry *, char *, int);
static struct dentry *minix_follow_link(struct dentry *, struct dentry *);
/*
* symlinks can't do much...
......@@ -40,8 +40,10 @@ struct inode_operations minix_symlink_inode_operations = {
NULL /* permission */
};
static struct dentry * minix_follow_link(struct inode * inode, struct dentry * base)
static struct dentry * minix_follow_link(struct dentry * dentry,
struct dentry * base)
{
struct inode *inode = dentry->d_inode;
struct buffer_head * bh;
bh = minix_bread(inode, 0, 0);
......@@ -55,7 +57,7 @@ static struct dentry * minix_follow_link(struct inode * inode, struct dentry * b
return base;
}
static int minix_readlink(struct inode * inode, char * buffer, int buflen)
static int minix_readlink(struct dentry * dentry, char * buffer, int buflen)
{
struct buffer_head * bh;
int i;
......@@ -63,7 +65,7 @@ static int minix_readlink(struct inode * inode, char * buffer, int buflen)
if (buflen > 1023)
buflen = 1023;
bh = minix_bread(inode, 0, 0);
bh = minix_bread(dentry->d_inode, 0, 0);
if (!bh)
return 0;
i = 0;
......
......@@ -221,33 +221,28 @@ void put_write_access(struct inode * inode)
}
/*
* This is called when everything else fails, and we actually have
* to go to the low-level filesystem to find out what we should do..
*
* We get the directory semaphore, and after getting that we also
* make sure that nobody added the entry to the dcache in the meantime..
* "." and ".." are special - ".." especially so because it has to be able
* to know about the current root directory and parent relationships
*/
static struct dentry * real_lookup(struct dentry * parent, struct qstr * name)
static struct dentry * reserved_lookup(struct dentry * parent, struct qstr * name)
{
struct dentry * result;
struct inode *dir = parent->d_inode;
struct dentry *result = NULL;
if (name->name[0] == '.') {
switch (name->len) {
default:
break;
case 2:
if (name->name[1] != '.')
break;
down(&dir->i_sem);
result = d_lookup(parent, name);
if (!result) {
struct dentry * dentry = d_alloc(parent, name);
result = ERR_PTR(-ENOMEM);
if (dentry) {
int error = dir->i_op->lookup(dir, dentry);
result = dentry;
if (error) {
dput(dentry);
result = ERR_PTR(error);
}
if (parent != current->fs->root)
parent = parent->d_covers->d_parent;
/* fallthrough */
case 1:
result = parent;
}
}
up(&dir->i_sem);
return result;
return dget(result);
}
/*
......@@ -274,28 +269,40 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name)
}
/*
* "." and ".." are special - ".." especially so because it has to be able
* to know about the current root directory and parent relationships
* This is called when everything else fails, and we actually have
* to go to the low-level filesystem to find out what we should do..
*
* We get the directory semaphore, and after getting that we also
* make sure that nobody added the entry to the dcache in the meantime..
*/
static struct dentry * reserved_lookup(struct dentry * parent, struct qstr * name)
static struct dentry * real_lookup(struct dentry * parent, struct qstr * name)
{
struct dentry *result = NULL;
if (name->name[0] == '.') {
switch (name->len) {
default:
break;
case 2:
if (name->name[1] != '.')
break;
struct dentry * result;
struct inode *dir = parent->d_inode;
if (parent != current->fs->root)
parent = parent->d_covers->d_parent;
/* fallthrough */
case 1:
result = parent;
down(&dir->i_sem);
/*
* First re-do the cached lookup just in case it was created
* while we waited for the directory semaphore..
*
* FIXME! This could use version numbering or similar to
* avoid unnecessary cache lookups.
*/
result = cached_lookup(parent, name);
if (!result) {
struct dentry * dentry = d_alloc(parent, name);
result = ERR_PTR(-ENOMEM);
if (dentry) {
int error = dir->i_op->lookup(dir, dentry);
result = dentry;
if (error) {
dput(dentry);
result = ERR_PTR(error);
}
}
return dget(result);
}
up(&dir->i_sem);
return result;
}
static struct dentry * do_follow_link(struct dentry *base, struct dentry *dentry)
......@@ -308,7 +315,7 @@ static struct dentry * do_follow_link(struct dentry *base, struct dentry *dentry
current->link_count++;
/* This eats the base */
result = inode->i_op->follow_link(inode, base);
result = inode->i_op->follow_link(dentry, base);
current->link_count--;
dput(dentry);
return result;
......@@ -632,7 +639,7 @@ struct dentry * open_namei(const char * pathname, int flag, int mode)
if (inode->i_sb && inode->i_sb->dq_op)
inode->i_sb->dq_op->initialize(inode, -1);
error = do_truncate(inode, 0);
error = do_truncate(dentry, 0);
}
put_write_access(inode);
if (error)
......@@ -1076,7 +1083,7 @@ static inline int do_link(const char * oldname, const char * newname)
if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op)
dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1);
error = dir->d_inode->i_op->link(inode, dir->d_inode, new_dentry);
error = dir->d_inode->i_op->link(old_dentry, dir->d_inode, new_dentry);
exit_lock:
unlock_dir(dir);
......
......@@ -106,9 +106,9 @@ ncp_dir_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
* Dentry operations routines
*/
static int ncp_lookup_validate(struct dentry *);
static void ncp_delete_dentry(struct dentry *);
static int ncp_hash_dentry(struct dentry *, struct qstr *);
static int ncp_compare_dentry (struct dentry *, struct qstr *, struct qstr *);
static void ncp_delete_dentry(struct dentry *);
static struct dentry_operations ncp_dentry_operations =
{
......@@ -125,18 +125,22 @@ static struct dentry_operations ncp_dentry_operations =
*/
#define tolower(c) (((c) >= 'A' && (c) <= 'Z') ? (c)-('A'-'a') : (c))
/*
* Note: leave the hash unchanged if the directory
* is case-sensitive.
*/
static int
ncp_hash_dentry(struct dentry *dentry, struct qstr *this)
{
unsigned long hash;
int i;
if (!ncp_case_sensitive(dentry->d_inode)) {
hash = init_name_hash();
for (i=0; i<this->len ; i++)
hash = partial_name_hash(tolower(this->name[i]),hash);
this->hash = end_name_hash(hash);
}
return 0;
}
......@@ -202,45 +206,17 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
*/
ino_t ncp_invent_inos(unsigned long n)
{
static ino_t ino = 1;
static ino_t ino = 2;
if (ino + 2*n < ino)
{
/* wrap around */
ino += n;
ino = 2;
}
ino += n;
return ino;
}
/*
* Check whether a dentry already exists for the given name,
* and return the inode number if it has an inode. This is
* needed to keep getcwd() working.
*/
static ino_t
find_inode_number(struct dentry *dir, struct qstr *name)
{
unsigned long hash;
int i;
struct dentry * dentry;
ino_t ino = 0;
hash = init_name_hash();
for (i=0; i<name->len ; i++)
hash = partial_name_hash(tolower(name->name[i]),hash);
name->hash = end_name_hash(hash);
dentry = d_lookup(dir, name);
if (dentry)
{
if (dentry->d_inode)
ino = dentry->d_inode->i_ino;
dput(dentry);
}
return ino;
}
static inline int
ncp_single_volume(struct ncp_server *server)
{
......
......@@ -15,11 +15,12 @@
#include <linux/fcntl.h>
#include <linux/stat.h>
#include <linux/mm.h>
#include <linux/ncp_fs.h>
#include <linux/locks.h>
#include "ncplib_kernel.h"
#include <linux/malloc.h>
#include <linux/ncp_fs.h>
#include "ncplib_kernel.h"
static inline int min(int a, int b)
{
return a < b ? a : b;
......@@ -65,7 +66,7 @@ int ncp_make_open(struct inode *inode, int right)
result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
NULL, NULL, OC_MODE_OPEN,
0, AR_READ, &finfo);
if (!result) {
if (result) {
#ifdef NCPFS_PARANOIA
printk(KERN_DEBUG "ncp_make_open: failed, result=%d\n", result);
#endif
......@@ -82,11 +83,7 @@ printk(KERN_DEBUG "ncp_make_open: failed, result=%d\n", result);
#ifdef NCPFS_PARANOIA
printk(KERN_DEBUG "ncp_make_open: file open, access=%x\n", access);
#endif
if (((right == O_RDONLY) && ((access == O_RDONLY)
|| (access == O_RDWR)))
|| ((right == O_WRONLY) && ((access == O_WRONLY)
|| (access == O_RDWR)))
|| ((right == O_RDWR) && (access == O_RDWR)))
if (access == right || access == O_RDWR)
error = 0;
out_unlock:
......@@ -231,7 +228,7 @@ ncp_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
}
}
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_mtime = inode->i_atime = CURRENT_TIME;
file->f_pos = pos;
......
......@@ -37,7 +37,7 @@ extern int close_fp(struct file *filp);
static void ncp_read_inode(struct inode *);
static void ncp_put_inode(struct inode *);
static void ncp_delete_inode(struct inode *);
static int ncp_notify_change(struct inode *, struct iattr *);
static int ncp_notify_change(struct dentry *, struct iattr *);
static void ncp_put_super(struct super_block *);
static int ncp_statfs(struct super_block *, struct statfs *, int);
......@@ -210,7 +210,7 @@ static void ncp_init_root(struct ncp_server *server,
i->entryName[0] = '\0';
root->finfo.opened= 0;
info->ino = 1;
info->ino = 2; /* tradition */
info->nw_info = root->finfo;
}
......@@ -354,7 +354,7 @@ static void ncp_put_super(struct super_block *sb)
ncp_unlock_server(server);
close_fp(server->ncp_filp);
kill_proc(server->m.wdog_pid, SIGTERM, 0);
kill_proc(server->m.wdog_pid, SIGTERM, 1);
ncp_kfree_s(server->packet, server->packet_size);
......@@ -387,30 +387,34 @@ static int ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
}
static int ncp_notify_change(struct inode *inode, struct iattr *attr)
static int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = dentry->d_inode;
int result = 0;
int info_mask;
struct nw_modify_dos_info info;
if (!ncp_conn_valid(NCP_SERVER(inode))) {
return -EIO;
}
if ((result = inode_change_ok(inode, attr)) < 0)
return result;
result = -EIO;
if (!ncp_conn_valid(NCP_SERVER(inode)))
goto out;
result = inode_change_ok(inode, attr);
if (result < 0)
goto out;
result = -EPERM;
if (((attr->ia_valid & ATTR_UID) &&
(attr->ia_uid != NCP_SERVER(inode)->m.uid)))
return -EPERM;
goto out;
if (((attr->ia_valid & ATTR_GID) &&
(attr->ia_uid != NCP_SERVER(inode)->m.gid)))
return -EPERM;
goto out;
if (((attr->ia_valid & ATTR_MODE) &&
(attr->ia_mode &
~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
return -EPERM;
goto out;
info_mask = 0;
memset(&info, 0, sizeof(info));
......@@ -455,7 +459,8 @@ static int ncp_notify_change(struct inode *inode, struct iattr *attr)
if ((attr->ia_valid & ATTR_SIZE) != 0) {
int written;
DPRINTK(KERN_DEBUG "ncpfs: trying to change size to %ld\n", attr->ia_size);
DPRINTK(KERN_DEBUG "ncpfs: trying to change size to %ld\n",
attr->ia_size);
if ((result = ncp_make_open(inode, O_RDWR)) < 0) {
return -EACCES;
......@@ -467,11 +472,8 @@ static int ncp_notify_change(struct inode *inode, struct iattr *attr)
closing the file */
result = ncp_make_closed(inode);
}
/*
* We need a dentry here ...
*/
/* ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode); */
ncp_invalid_dir_cache(dentry->d_parent->d_inode);
out:
return result;
}
......
......@@ -64,7 +64,7 @@ static int nfs_mkdir(struct inode *, struct dentry *, int);
static int nfs_rmdir(struct inode *, struct dentry *);
static int nfs_unlink(struct inode *, struct dentry *);
static int nfs_symlink(struct inode *, struct dentry *, const char *);
static int nfs_link(struct inode *, struct inode *, struct dentry *);
static int nfs_link(struct dentry *, struct inode *, struct dentry *);
static int nfs_mknod(struct inode *, struct dentry *, int, int);
static int nfs_rename(struct inode *, struct dentry *,
struct inode *, struct dentry *);
......@@ -108,8 +108,11 @@ struct inode_operations nfs_dir_inode_operations = {
static int
nfs_dir_open(struct inode *dir, struct file *file)
{
dfprintk(VFS, "NFS: nfs_dir_open(%x/%ld)\n", dir->i_dev, dir->i_ino);
return nfs_revalidate_inode(NFS_SERVER(dir), dir);
struct dentry *dentry = file->f_dentry;
dfprintk(VFS, "NFS: nfs_dir_open(%s/%s)\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
return nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
}
static ssize_t
......@@ -133,7 +136,8 @@ static struct nfs_dirent dircache[NFS_MAX_DIRCACHE];
static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
struct inode *inode = filp->f_dentry->d_inode;
struct dentry *dentry = filp->f_dentry;
struct inode *inode = dentry->d_inode;
static struct wait_queue *readdir_wait = NULL;
struct wait_queue **waitp = NULL;
struct nfs_dirent *cache, *free;
......@@ -144,14 +148,17 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
__u32 *entry;
char *name, *start;
dfprintk(VFS, "NFS: nfs_readdir(%x/%ld)\n", inode->i_dev, inode->i_ino);
dfprintk(VFS, "NFS: nfs_readdir(%s/%s)\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
result = -EBADF;
if (!inode || !S_ISDIR(inode->i_mode)) {
printk("nfs_readdir: inode is NULL or not a directory\n");
return -EBADF;
goto out;
}
if ((result = nfs_revalidate_inode(NFS_SERVER(inode), inode)) < 0)
return result;
result = nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
if (result < 0)
goto out;
/*
* Try to find the entry in the cache
......@@ -250,7 +257,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
goto done;
}
result = nfs_proc_readdir(NFS_SERVER(inode), NFS_FH(inode),
result = nfs_proc_readdir(NFS_SERVER(inode), NFS_FH(dentry),
cookie, PAGE_SIZE, cache->entry);
if (result <= 0)
goto done;
......@@ -300,6 +307,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
wake_up(&cache->wait);
wake_up(&readdir_wait);
out:
return result;
}
......@@ -449,11 +457,21 @@ inode->i_ino, inode->i_count, inode->i_nlink);
#endif
}
static struct dentry_operations nfs_dentry_operations = {
/*
* Called when the dentry is being freed to release private memory.
*/
static void nfs_dentry_release(struct dentry *dentry)
{
if (dentry->d_fsdata)
kfree(dentry->d_fsdata);
}
struct dentry_operations nfs_dentry_operations = {
nfs_lookup_revalidate, /* d_validate(struct dentry *) */
0, /* d_hash */
0, /* d_compare */
nfs_dentry_delete /* d_delete(struct dentry *) */
NULL, /* d_hash */
NULL, /* d_compare */
nfs_dentry_delete, /* d_delete(struct dentry *) */
nfs_dentry_release /* d_release(struct dentry *) */
};
/*
......@@ -470,16 +488,20 @@ void nfs_renew_times(struct dentry * dentry)
}
}
static void nfs_set_fh(struct dentry *dentry, struct nfs_fh *fhandle)
{
*((struct nfs_fh *) dentry->d_fsdata) = *fhandle;
}
static int nfs_lookup(struct inode *dir, struct dentry * dentry)
{
int len = dentry->d_name.len;
struct inode *inode;
int error;
struct nfs_fh fhandle;
struct nfs_fattr fattr;
dfprintk(VFS, "NFS: lookup(%x/%ld, %.*s)\n",
dir->i_dev, dir->i_ino, len, dentry->d_name.name);
dfprintk(VFS, "NFS: lookup(%s/%s)\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
if (!dir || !S_ISDIR(dir->i_mode)) {
printk("nfs_lookup: inode is NULL or not a directory\n");
......@@ -487,17 +509,26 @@ static int nfs_lookup(struct inode *dir, struct dentry * dentry)
}
error = -ENAMETOOLONG;
if (len > NFS_MAXNAMLEN)
if (dentry->d_name.len > NFS_MAXNAMLEN)
goto out;
error = nfs_proc_lookup(NFS_SERVER(dir), NFS_FH(dir),
error = -ENOMEM;
if (!dentry->d_fsdata) {
dentry->d_fsdata = kmalloc(sizeof(struct nfs_fh), GFP_KERNEL);
if (!dentry->d_fsdata)
goto out;
}
dentry->d_op = &nfs_dentry_operations;
error = nfs_proc_lookup(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
dentry->d_name.name, &fhandle, &fattr);
inode = NULL;
if (error == -ENOENT)
goto no_entry;
if (!error) {
error = -EACCES;
inode = nfs_fhget(dir->i_sb, &fhandle, &fattr);
nfs_set_fh(dentry, &fhandle);
inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr);
if (inode) {
#ifdef NFS_PARANOIA
if (inode->i_count > (S_ISDIR(inode->i_mode) ? 1 : inode->i_nlink))
......@@ -506,7 +537,6 @@ dentry->d_parent->d_name.name, dentry->d_name.name,
inode->i_ino, inode->i_count, inode->i_nlink);
#endif
no_entry:
dentry->d_op = &nfs_dentry_operations;
d_add(dentry, inode);
nfs_renew_times(dentry);
error = 0;
......@@ -530,6 +560,7 @@ static int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
struct inode *inode;
int error = -EACCES;
nfs_set_fh(dentry, fhandle);
inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
if (inode) {
#ifdef NFS_PARANOIA
......@@ -578,7 +609,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode)
* Invalidate the dir cache before the operation to avoid a race.
*/
nfs_invalidate_dircache(dir);
error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir),
error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
dentry->d_name.name, &sattr, &fhandle, &fattr);
if (!error)
error = nfs_instantiate(dentry, &fhandle, &fattr);
......@@ -616,7 +647,7 @@ static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rde
sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
nfs_invalidate_dircache(dir);
error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir),
error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
dentry->d_name.name, &sattr, &fhandle, &fattr);
if (!error)
error = nfs_instantiate(dentry, &fhandle, &fattr);
......@@ -652,7 +683,7 @@ static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
nfs_invalidate_dircache(dir);
error = nfs_proc_mkdir(NFS_SERVER(dir), NFS_FH(dir),
error = nfs_proc_mkdir(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
dentry->d_name.name, &sattr, &fhandle, &fattr);
/*
......@@ -717,8 +748,8 @@ dentry->d_inode->i_count, dentry->d_inode->i_nlink);
dentry->d_inode->i_nlink --;
d_delete(dentry);
nfs_invalidate_dircache(dir);
error = nfs_proc_rmdir(NFS_SERVER(dir),
NFS_FH(dir), dentry->d_name.name);
error = nfs_proc_rmdir(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
dentry->d_name.name);
if (!error) {
if (rehash)
d_add(dentry, NULL);
......@@ -839,8 +870,8 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
nfs_invalidate_dircache(dir);
error = nfs_proc_rename(NFS_SERVER(dir),
NFS_FH(dir), dentry->d_name.name,
NFS_FH(dir), silly);
NFS_FH(dentry->d_parent), dentry->d_name.name,
NFS_FH(dentry->d_parent), silly);
if (!error) {
nfs_renew_times(dentry);
d_move(dentry, sdentry);
......@@ -914,8 +945,8 @@ inode->i_count, inode->i_nlink);
d_delete(dentry);
}
nfs_invalidate_dircache(dir);
error = nfs_proc_remove(NFS_SERVER(dir),
NFS_FH(dir), dentry->d_name.name);
error = nfs_proc_remove(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
dentry->d_name.name);
/*
* Rehash the negative dentry if the operation succeeded.
*/
......@@ -998,7 +1029,7 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
*/
d_drop(dentry);
nfs_invalidate_dircache(dir);
error = nfs_proc_symlink(NFS_SERVER(dir), NFS_FH(dir),
error = nfs_proc_symlink(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
dentry->d_name.name, symname, &sattr);
if (!error) {
nfs_renew_times(dentry->d_parent);
......@@ -1012,13 +1043,14 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
}
static int
nfs_link(struct inode *inode, struct inode *dir, struct dentry *dentry)
nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
{
struct inode *inode = old_dentry->d_inode;
int error;
dfprintk(VFS, "NFS: link(%x/%ld -> %x/%ld, %s)\n",
inode->i_dev, inode->i_ino,
dir->i_dev, dir->i_ino, dentry->d_name.name);
dfprintk(VFS, "NFS: link(%s/%s -> %s/%s)\n",
old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
dentry->d_parent->d_name.name, dentry->d_name.name);
if (!dir || !S_ISDIR(dir->i_mode)) {
printk("nfs_link: dir is NULL or not a directory\n");
......@@ -1029,13 +1061,21 @@ nfs_link(struct inode *inode, struct inode *dir, struct dentry *dentry)
if (dentry->d_name.len > NFS_MAXNAMLEN)
goto out;
/*
* Drop the dentry in advance to force a new lookup.
* Since nfs_proc_link doesn't return a filehandle,
* we can't use the existing dentry.
*/
d_drop(dentry);
nfs_invalidate_dircache(dir);
error = nfs_proc_link(NFS_SERVER(inode), NFS_FH(inode), NFS_FH(dir),
dentry->d_name.name);
error = nfs_proc_link(NFS_DSERVER(old_dentry), NFS_FH(old_dentry),
NFS_FH(dentry->d_parent), dentry->d_name.name);
if (!error) {
inode->i_count ++;
inode->i_nlink ++; /* no need to wait for nfs_refresh_inode() */
d_instantiate(dentry, inode);
/*
* Update the link count immediately, as some apps
* (e.g. pine) test this after making a link.
*/
inode->i_nlink++;
}
out:
return error;
......@@ -1181,9 +1221,9 @@ new_inode->i_count, new_inode->i_nlink);
nfs_invalidate_dircache(new_dir);
nfs_invalidate_dircache(old_dir);
error = nfs_proc_rename(NFS_SERVER(old_dir),
NFS_FH(old_dir), old_dentry->d_name.name,
NFS_FH(new_dir), new_dentry->d_name.name);
error = nfs_proc_rename(NFS_DSERVER(old_dentry),
NFS_FH(old_dentry->d_parent), old_dentry->d_name.name,
NFS_FH(new_dentry->d_parent), new_dentry->d_name.name);
if (!error) {
/* Update the dcache if needed */
if (rehash)
......
......@@ -109,15 +109,14 @@ nfs_file_close(struct inode *inode, struct file *file)
static ssize_t
nfs_file_read(struct file * file, char * buf, size_t count, loff_t *ppos)
{
struct inode * inode = file->f_dentry->d_inode;
struct dentry * dentry = file->f_dentry;
ssize_t result;
dfprintk(VFS, "nfs: read(%x/%ld, %lu@%lu)\n",
inode->i_dev, inode->i_ino,
(unsigned long) count,
(unsigned long) *ppos);
dfprintk(VFS, "nfs: read(%s/%s, %lu@%lu)\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
(unsigned long) count, (unsigned long) *ppos);
result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
result = nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
if (!result)
result = generic_file_read(file, buf, count, ppos);
return result;
......@@ -126,12 +125,13 @@ nfs_file_read(struct file * file, char * buf, size_t count, loff_t *ppos)
static int
nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
{
struct inode *inode = file->f_dentry->d_inode;
struct dentry *dentry = file->f_dentry;
int status;
dfprintk(VFS, "nfs: mmap(%x/%ld)\n", inode->i_dev, inode->i_ino);
dfprintk(VFS, "nfs: mmap(%s/%s)\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
status = nfs_revalidate_inode(NFS_SERVER(inode), inode);
status = nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
if (!status)
status = generic_file_mmap(file, vma);
return status;
......@@ -163,31 +163,33 @@ nfs_fsync(struct file *file, struct dentry *dentry)
static ssize_t
nfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
struct inode * inode = file->f_dentry->d_inode;
struct dentry * dentry = file->f_dentry;
struct inode * inode = dentry->d_inode;
ssize_t result;
dfprintk(VFS, "nfs: write(%x/%ld (%d), %lu@%lu)\n",
inode->i_dev, inode->i_ino, inode->i_count,
(unsigned long) count, (unsigned long) *ppos);
dfprintk(VFS, "nfs: write(%s/%s (%d), %lu@%lu)\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
inode->i_count, (unsigned long) count, (unsigned long) *ppos);
if (!inode) {
printk("nfs_file_write: inode = NULL\n");
return -EINVAL;
}
if (IS_SWAPFILE(inode)) {
printk("NFS: attempt to write to active swap file!\n");
return -EBUSY;
}
result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
result = -EBUSY;
if (IS_SWAPFILE(inode))
goto out_swapfile;
result = nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
if (result)
goto out;
/* N.B. This should be impossible now -- inodes can't change mode */
if (!S_ISREG(inode->i_mode)) {
#ifdef NFS_PARANOIA
/* N.B. This should be impossible now -- inodes can't change mode */
if (!S_ISREG(inode->i_mode)) {
printk("nfs_file_write: write to non-file, mode %07o\n",
inode->i_mode);
return -EINVAL;
}
}
#endif
result = count;
if (!count)
goto out;
......@@ -198,6 +200,10 @@ nfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
result = generic_file_write(file, buf, count, ppos);
out:
return result;
out_swapfile:
printk("NFS: attempt to write to active swap file!\n");
goto out;
}
/*
......
......@@ -38,7 +38,7 @@
static void nfs_read_inode(struct inode *);
static void nfs_put_inode(struct inode *);
static void nfs_delete_inode(struct inode *);
static int nfs_notify_change(struct inode *, struct iattr *);
static int nfs_notify_change(struct dentry *, struct iattr *);
static void nfs_put_super(struct super_block *);
static int nfs_statfs(struct super_block *, struct statfs *, int);
......@@ -180,15 +180,15 @@ struct super_block *
nfs_read_super(struct super_block *sb, void *raw_data, int silent)
{
struct nfs_mount_data *data = (struct nfs_mount_data *) raw_data;
struct sockaddr_in srvaddr;
struct nfs_server *server;
struct rpc_timeout timeparms;
struct rpc_xprt *xprt;
struct rpc_clnt *clnt;
struct nfs_fh *root_fh;
struct inode *root_inode;
unsigned int authflavor;
int tcp;
kdev_t dev = sb->s_dev;
struct inode *root_inode;
struct sockaddr_in srvaddr;
struct rpc_timeout timeparms;
MOD_INC_USE_COUNT;
if (!data)
......@@ -211,7 +211,6 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
lock_super(sb);
sb->s_magic = NFS_SUPER_MAGIC;
sb->s_dev = dev;
sb->s_op = &nfs_sops;
sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits);
sb->u.nfs_sb.s_root = data->root;
......@@ -234,21 +233,19 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
timeparms.to_maxval = tcp? RPC_MAX_TCP_TIMEOUT : RPC_MAX_UDP_TIMEOUT;
timeparms.to_exponential = 1;
/* Choose authentication flavor */
if (data->flags & NFS_MOUNT_SECURE) {
authflavor = RPC_AUTH_DES;
} else if (data->flags & NFS_MOUNT_KERBEROS) {
authflavor = RPC_AUTH_KRB;
} else {
authflavor = RPC_AUTH_UNIX;
}
/* Now create transport and client */
xprt = xprt_create_proto(tcp? IPPROTO_TCP : IPPROTO_UDP,
&srvaddr, &timeparms);
if (xprt == NULL)
goto out_no_xprt;
/* Choose authentication flavor */
authflavor = RPC_AUTH_UNIX;
if (data->flags & NFS_MOUNT_SECURE)
authflavor = RPC_AUTH_DES;
else if (data->flags & NFS_MOUNT_KERBEROS)
authflavor = RPC_AUTH_KRB;
clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
NFS_VERSION, authflavor);
if (clnt == NULL)
......@@ -267,12 +264,20 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
* Keep the super block locked while we try to get
* the root fh attributes.
*/
root_fh = kmalloc(sizeof(struct nfs_fh), GFP_KERNEL);
if (!root_fh)
goto out_no_fh;
*root_fh = data->root;
root_inode = nfs_fhget(sb, &data->root, NULL);
if (!root_inode)
goto out_no_root;
sb->s_root = d_alloc_root(root_inode, NULL);
if (!sb->s_root)
goto out_no_root;
sb->s_root->d_op = &nfs_dentry_operations;
sb->s_root->d_fsdata = root_fh;
/* We're airborne */
unlock_super(sb);
......@@ -285,6 +290,8 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
out_no_root:
printk("nfs_read_super: get root inode failed\n");
iput(root_inode);
kfree(root_fh);
out_no_fh:
rpciod_down();
goto out_shutdown;
......@@ -352,36 +359,28 @@ struct inode *
nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle,
struct nfs_fattr *fattr)
{
struct nfs_fattr newfattr;
int error;
struct inode *inode;
struct inode *inode = NULL;
struct nfs_fattr newfattr;
if (!sb) {
printk("nfs_fhget: super block is NULL\n");
return NULL;
}
if (!sb)
goto out_bad_args;
if (!fattr) {
error = nfs_proc_getattr(&sb->u.nfs_sb.s_server, fhandle,
&newfattr);
if (error) {
printk("nfs_fhget: getattr error = %d\n", -error);
return NULL;
}
fattr = &newfattr;
error = nfs_proc_getattr(&sb->u.nfs_sb.s_server, fhandle,fattr);
if (error)
goto out_bad_attr;
}
if (!(inode = iget(sb, fattr->fileid))) {
printk("nfs_fhget: iget failed\n");
return NULL;
}
inode = iget(sb, fattr->fileid);
if (!inode)
goto out_no_inode;
#ifdef NFS_PARANOIA
if (inode->i_dev != sb->s_dev)
printk("nfs_fhget: impossible\n");
#endif
if (inode->i_ino != fattr->fileid) {
printk("nfs_fhget: unexpected inode from iget\n");
return inode;
}
if (inode->i_ino != fattr->fileid)
goto out_bad_id;
/*
* Check whether the mode has been set, as we only want to
......@@ -412,29 +411,41 @@ printk("nfs_fhget: impossible\n");
inode->i_size = fattr->size;
inode->i_mtime = fattr->mtime.seconds;
NFS_OLDMTIME(inode) = fattr->mtime.seconds;
*NFS_FH(inode) = *fhandle;
}
if (memcmp(NFS_FH(inode), fhandle, sizeof(struct nfs_fh)))
printk("nfs_fhget: fhandle changed!\n");
nfs_refresh_inode(inode, fattr);
dprintk("NFS: fhget(%x/%ld ct=%d)\n",
inode->i_dev, inode->i_ino,
inode->i_count);
out:
return inode;
out_bad_args:
printk("nfs_fhget: super block is NULL\n");
goto out;
out_bad_attr:
printk("nfs_fhget: getattr error = %d\n", -error);
goto out;
out_no_inode:
printk("nfs_fhget: iget failed\n");
goto out;
out_bad_id:
printk("nfs_fhget: unexpected inode from iget\n");
goto out;
}
int
nfs_notify_change(struct inode *inode, struct iattr *attr)
nfs_notify_change(struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = dentry->d_inode;
int error;
struct nfs_sattr sattr;
struct nfs_fattr fattr;
int error;
/*
* Make sure the inode is up-to-date.
*/
error = nfs_revalidate(inode);
error = nfs_revalidate(dentry);
if (error) {
#ifdef NFS_PARANOIA
printk("nfs_notify_change: revalidate failed, error=%d\n", error);
......@@ -470,7 +481,7 @@ printk("nfs_notify_change: revalidate failed, error=%d\n", error);
sattr.atime.useconds = 0;
}
error = nfs_proc_setattr(NFS_SERVER(inode), NFS_FH(inode),
error = nfs_proc_setattr(NFS_DSERVER(dentry), NFS_FH(dentry),
&sattr, &fattr);
if (error)
goto out;
......@@ -497,9 +508,9 @@ printk("nfs_notify_change: revalidate failed, error=%d\n", error);
* Externally visible revalidation function
*/
int
nfs_revalidate(struct inode *inode)
nfs_revalidate(struct dentry *dentry)
{
return nfs_revalidate_inode(NFS_SERVER(inode), inode);
return nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
}
/*
......@@ -507,38 +518,43 @@ nfs_revalidate(struct inode *inode)
* the cached attributes have to be refreshed.
*/
int
_nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
_nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry)
{
struct nfs_fattr fattr;
struct inode *inode = dentry->d_inode;
int status = 0;
struct nfs_fattr fattr;
if (jiffies - NFS_READTIME(inode) < NFS_ATTRTIMEO(inode))
goto out;
dfprintk(PAGECACHE, "NFS: revalidating %x/%ld inode\n",
inode->i_dev, inode->i_ino);
status = nfs_proc_getattr(server, NFS_FH(inode), &fattr);
dfprintk(PAGECACHE, "NFS: revalidating %s/%s, ino=%ld\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
inode->i_ino);
status = nfs_proc_getattr(server, NFS_FH(dentry), &fattr);
if (status) {
#ifdef NFS_PARANOIA
printk("nfs_revalidate_inode: getattr failed, error=%d\n", status);
printk("nfs_revalidate_inode: %s/%s getattr failed, ino=%ld, error=%d\n",
dentry->d_parent->d_name.name, dentry->d_name.name, inode->i_ino, status);
#endif
goto done;
goto out;
}
status = nfs_refresh_inode(inode, &fattr);
if (status)
goto done;
if (status) {
#ifdef NFS_PARANOIA
printk("nfs_revalidate_inode: %s/%s refresh failed, ino=%ld, error=%d\n",
dentry->d_parent->d_name.name, dentry->d_name.name, inode->i_ino, status);
#endif
goto out;
}
if (fattr.mtime.seconds == NFS_OLDMTIME(inode)) {
/* Update attrtimeo value */
if ((NFS_ATTRTIMEO(inode) <<= 1) > NFS_MAXATTRTIMEO(inode))
NFS_ATTRTIMEO(inode) = NFS_MAXATTRTIMEO(inode);
}
NFS_OLDMTIME(inode) = fattr.mtime.seconds;
done:
dfprintk(PAGECACHE,
"NFS: inode %x/%ld revalidation complete (status %d).\n",
inode->i_dev, inode->i_ino, status);
dfprintk(PAGECACHE, "NFS: %s/%s revalidation complete\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
out:
return status;
}
......@@ -569,7 +585,8 @@ nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
goto out;
}
if (inode->i_ino != fattr->fileid) {
printk("nfs_refresh_inode: inode number mismatch\n");
printk("nfs_refresh_inode: mismatch, ino=%ld, fattr=%d\n",
inode->i_ino, fattr->fileid);
goto out;
}
......
......@@ -65,8 +65,8 @@ nfs_readreq_setup(struct nfs_rreq *req, struct nfs_fh *fh,
/*
* Read a page synchronously.
*/
int
nfs_readpage_sync(struct inode *inode, struct page *page)
static int
nfs_readpage_sync(struct dentry *dentry, struct inode *inode, struct page *page)
{
struct nfs_rreq rqst;
unsigned long offset = page->offset;
......@@ -83,12 +83,13 @@ nfs_readpage_sync(struct inode *inode, struct page *page)
if (count < rsize)
rsize = count;
dprintk("NFS: nfs_proc_read(%s, (%x,%lx), %ld, %d, %p)\n",
NFS_SERVER(inode)->hostname, inode->i_dev,
inode->i_ino, offset, rsize, buffer);
dprintk("NFS: nfs_proc_read(%s, (%s/%s), %ld, %d, %p)\n",
NFS_SERVER(inode)->hostname,
dentry->d_parent->d_name.name, dentry->d_name.name,
offset, rsize, buffer);
/* Set up arguments and perform rpc call */
nfs_readreq_setup(&rqst, NFS_FH(inode), offset, buffer, rsize);
nfs_readreq_setup(&rqst, NFS_FH(dentry), offset, buffer, rsize);
result = rpc_call(NFS_CLIENT(inode), NFSPROC_READ,
&rqst.ra_args, &rqst.ra_res, flags);
......@@ -160,7 +161,8 @@ nfs_readpage_result(struct rpc_task *task)
}
static inline int
nfs_readpage_async(struct inode *inode, struct page *page)
nfs_readpage_async(struct dentry *dentry, struct inode *inode,
struct page *page)
{
struct nfs_rreq *req;
int result, flags;
......@@ -175,7 +177,7 @@ nfs_readpage_async(struct inode *inode, struct page *page)
}
/* Initialize request */
nfs_readreq_setup(req, NFS_FH(inode), page->offset,
nfs_readreq_setup(req, NFS_FH(dentry), page->offset,
(void *) page_address(page), PAGE_SIZE);
req->ra_inode = inode;
req->ra_page = page;
......@@ -209,8 +211,9 @@ nfs_readpage_async(struct inode *inode, struct page *page)
* - The server is congested.
*/
int
nfs_readpage(struct inode *inode, struct page *page)
nfs_readpage(struct dentry *dentry, struct page *page)
{
struct inode *inode = dentry->d_inode;
unsigned long address;
int error = -1;
......@@ -218,11 +221,11 @@ nfs_readpage(struct inode *inode, struct page *page)
set_bit(PG_locked, &page->flags);
address = page_address(page);
atomic_inc(&page->count);
if (!IS_SWAPFILE(inode) && !PageError(page)
&& NFS_SERVER(inode)->rsize >= PAGE_SIZE)
error = nfs_readpage_async(inode, page);
if (!IS_SWAPFILE(inode) && !PageError(page) &&
NFS_SERVER(inode)->rsize >= PAGE_SIZE)
error = nfs_readpage_async(dentry, inode, page);
if (error < 0) /* couldn't enqueue */
error = nfs_readpage_sync(inode, page);
error = nfs_readpage_sync(dentry, inode, page);
if (error < 0 && IS_SWAPFILE(inode))
printk("Aiee.. nfs swap-in of page failed!\n");
free_page(address);
......
......@@ -18,8 +18,8 @@
#include <asm/uaccess.h>
static int nfs_readlink(struct inode *, char *, int);
static struct dentry *nfs_follow_link(struct inode *, struct dentry *);
static int nfs_readlink(struct dentry *, char *, int);
static struct dentry *nfs_follow_link(struct dentry *, struct dentry *);
/*
* symlinks can't do much...
......@@ -44,19 +44,20 @@ struct inode_operations nfs_symlink_inode_operations = {
NULL /* permission */
};
static int nfs_readlink(struct inode *inode, char *buffer, int buflen)
static int nfs_readlink(struct dentry *dentry, char *buffer, int buflen)
{
int error;
unsigned int len;
char *res;
void *mem;
dfprintk(VFS, "nfs: readlink(%x/%ld)\n", inode->i_dev, inode->i_ino);
dfprintk(VFS, "nfs: readlink(%s/%s)\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
if (buflen > NFS_MAXPATHLEN)
buflen = NFS_MAXPATHLEN;
error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), &mem,
&res, &len, buflen);
error = nfs_proc_readlink(NFS_DSERVER(dentry), NFS_FH(dentry),
&mem, &res, &len, buflen);
if (! error) {
copy_to_user(buffer, res, len);
put_user('\0', buffer + len);
......@@ -66,34 +67,41 @@ static int nfs_readlink(struct inode *inode, char *buffer, int buflen)
return error;
}
static struct dentry * nfs_follow_link(struct inode * inode, struct dentry *base)
static struct dentry *
nfs_follow_link(struct dentry * dentry, struct dentry *base)
{
int error;
unsigned int len;
char *res;
void *mem;
char *path;
struct dentry *result;
dfprintk(VFS, "nfs: follow_link(%x/%ld)\n", inode->i_dev, inode->i_ino);
dfprintk(VFS, "nfs: follow_link(%s/%s)\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), &mem,
&res, &len, NFS_MAXPATHLEN);
error = nfs_proc_readlink(NFS_DSERVER(dentry), NFS_FH(dentry),
&mem, &res, &len, NFS_MAXPATHLEN);
result = ERR_PTR(error);
if (error)
goto out_dput;
if (error) {
dput(base);
return ERR_PTR(error);
}
result = ERR_PTR(-ENOMEM);
path = kmalloc(len + 1, GFP_KERNEL);
if (!path) {
dput(base);
kfree(mem);
return ERR_PTR(-ENOMEM);
}
if (!path)
goto out_mem;
memcpy(path, res, len);
path[len] = 0;
kfree(mem);
base = lookup_dentry(path, base, 1);
result = lookup_dentry(path, base, 1);
kfree(path);
return base;
out:
return result;
out_mem:
kfree(mem);
out_dput:
dput(base);
goto out;
}
......@@ -79,6 +79,7 @@ static void nfs_wback_result(struct rpc_task *task);
struct nfs_wreq {
struct rpc_listitem wb_list; /* linked list of req's */
struct rpc_task wb_task; /* RPC task */
struct dentry * wb_dentry; /* dentry referenced */
struct inode * wb_inode; /* inode referenced */
struct page * wb_page; /* page to be written */
unsigned int wb_offset; /* offset within page */
......@@ -169,16 +170,16 @@ transfer_page_lock(struct nfs_wreq *req)
* Offset is the data offset within the page.
*/
static int
nfs_writepage_sync(struct inode *inode, struct page *page,
unsigned long offset, unsigned int count)
nfs_writepage_sync(struct dentry *dentry, struct inode *inode,
struct page *page, unsigned long offset, unsigned int count)
{
struct nfs_fattr fattr;
unsigned int wsize = NFS_SERVER(inode)->wsize;
int result, refresh = 0, written = 0;
u8 *buffer;
struct nfs_fattr fattr;
dprintk("NFS: nfs_writepage_sync(%x/%ld %d@%ld)\n",
inode->i_dev, inode->i_ino,
dprintk("NFS: nfs_writepage_sync(%s/%s %d@%ld)\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
count, page->offset + offset);
buffer = (u8 *) page_address(page) + offset;
......@@ -188,7 +189,7 @@ nfs_writepage_sync(struct inode *inode, struct page *page,
if (count < wsize && !IS_SWAPFILE(inode))
wsize = count;
result = nfs_proc_write(NFS_SERVER(inode), NFS_FH(inode),
result = nfs_proc_write(NFS_DSERVER(dentry), NFS_FH(dentry),
IS_SWAPFILE(inode), offset, wsize,
buffer, &fattr);
......@@ -380,15 +381,15 @@ update_write_request(struct nfs_wreq *req, unsigned int first,
* Create and initialize a writeback request
*/
static inline struct nfs_wreq *
create_write_request(struct inode *inode, struct page *page,
unsigned int offset, unsigned int bytes)
create_write_request(struct dentry *dentry, struct inode *inode,
struct page *page, unsigned int offset, unsigned int bytes)
{
struct nfs_wreq *wreq;
struct rpc_clnt *clnt = NFS_CLIENT(inode);
struct rpc_task *task;
dprintk("NFS: create_write_request(%x/%ld, %ld+%d)\n",
inode->i_dev, inode->i_ino,
dprintk("NFS: create_write_request(%s/%s, %ld+%d)\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
page->offset + offset, bytes);
/* FIXME: Enforce hard limit on number of concurrent writes? */
......@@ -408,6 +409,7 @@ create_write_request(struct inode *inode, struct page *page,
goto out_req;
/* Put the task on inode's writeback request list. */
wreq->wb_dentry = dentry;
wreq->wb_inode = inode;
wreq->wb_pid = current->pid;
wreq->wb_page = page;
......@@ -504,9 +506,9 @@ wait_on_write_request(struct nfs_wreq *req)
* (for now), and we currently do this synchronously only.
*/
int
nfs_writepage(struct inode *inode, struct page *page)
nfs_writepage(struct dentry *dentry, struct page *page)
{
return nfs_writepage_sync(inode, page, 0, PAGE_SIZE);
return nfs_writepage_sync(dentry, dentry->d_inode, page, 0, PAGE_SIZE);
}
/*
......@@ -516,15 +518,16 @@ nfs_writepage(struct inode *inode, struct page *page)
* things with a page scheduled for an RPC call (e.g. invalidate it).
*/
int
nfs_updatepage(struct inode *inode, struct page *page, const char *buffer,
nfs_updatepage(struct dentry *dentry, struct page *page, const char *buffer,
unsigned long offset, unsigned int count, int sync)
{
struct inode *inode = dentry->d_inode;
struct nfs_wreq *req;
int status = 0, page_locked = 1;
u8 *page_addr;
dprintk("NFS: nfs_updatepage(%x/%ld %d@%ld, sync=%d)\n",
inode->i_dev, inode->i_ino,
dprintk("NFS: nfs_updatepage(%s/%s %d@%ld, sync=%d)\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
count, page->offset+offset, sync);
set_bit(PG_locked, &page->flags);
......@@ -535,7 +538,7 @@ nfs_updatepage(struct inode *inode, struct page *page, const char *buffer,
*/
if (NFS_SERVER(inode)->wsize < PAGE_SIZE) {
copy_from_user(page_addr + offset, buffer, count);
return nfs_writepage_sync(inode, page, offset, count);
return nfs_writepage_sync(dentry, inode, page, offset, count);
}
/*
......@@ -560,7 +563,7 @@ nfs_updatepage(struct inode *inode, struct page *page, const char *buffer,
/* Create the write request. */
status = -ENOBUFS;
req = create_write_request(inode, page, offset, count);
req = create_write_request(dentry, inode, page, offset, count);
if (!req)
goto done;
......@@ -823,7 +826,7 @@ nfs_wback_lock(struct rpc_task *task)
{
struct nfs_wreq *req = (struct nfs_wreq *) task->tk_calldata;
struct page *page = req->wb_page;
struct inode *inode = req->wb_inode;
struct dentry *dentry = req->wb_dentry;
dprintk("NFS: %4d nfs_wback_lock (status %d flags %x)\n",
task->tk_pid, task->tk_status, req->wb_flags);
......@@ -856,7 +859,7 @@ nfs_wback_lock(struct rpc_task *task)
}
/* Setup the task struct for a writeback call */
req->wb_args->fh = NFS_FH(inode);
req->wb_args->fh = NFS_FH(dentry);
req->wb_args->offset = page->offset + req->wb_offset;
req->wb_args->count = req->wb_bytes;
req->wb_args->buffer = (void *) (page_address(page) + req->wb_offset);
......@@ -873,16 +876,12 @@ static void
nfs_wback_result(struct rpc_task *task)
{
struct nfs_wreq *req = (struct nfs_wreq *) task->tk_calldata;
struct inode *inode;
struct page *page;
int status;
struct inode *inode = req->wb_inode;
struct page *page = req->wb_page;
int status = task->tk_status;
dprintk("NFS: %4d nfs_wback_result (status %d)\n",
task->tk_pid, task->tk_status);
inode = req->wb_inode;
page = req->wb_page;
status = task->tk_status;
task->tk_pid, status);
if (status < 0) {
/*
......
......@@ -230,7 +230,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap)
if (iap->ia_valid) {
iap->ia_valid |= ATTR_CTIME;
iap->ia_ctime = CURRENT_TIME;
err = notify_change(inode, iap);
err = notify_change(dentry, iap);
if (err)
return nfserrno(-err);
if (EX_ISSYNC(fhp->fh_export))
......@@ -475,7 +475,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
ia.ia_valid = ATTR_MODE;
ia.ia_mode = inode->i_mode & ~(S_ISUID | S_ISGID);
notify_change(inode, &ia);
notify_change(dentry, &ia);
}
fh_unlock(fhp); /* unlock inode */
......@@ -668,7 +668,7 @@ nfsd_truncate(struct svc_rqst *rqstp, struct svc_fh *fhp, unsigned long size)
fh_lock(fhp);
newattrs.ia_size = size;
newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
err = notify_change(inode, &newattrs);
err = notify_change(dentry, &newattrs);
if (!err) {
vmtruncate(inode, size);
if (inode->i_op && inode->i_op->truncate)
......@@ -710,7 +710,7 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp)
UPDATE_ATIME(inode);
/* N.B. Why does this call need a get_fs()?? */
oldfs = get_fs(); set_fs(KERNEL_DS);
err = inode->i_op->readlink(inode, buf, *lenp);
err = inode->i_op->readlink(dentry, buf, *lenp);
set_fs(oldfs);
if (err < 0)
......@@ -789,7 +789,7 @@ int
nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
char *fname, int len, struct svc_fh *tfhp)
{
struct dentry *ddir, *dnew;
struct dentry *ddir, *dnew, *dold;
struct inode *dirp, *dest;
int err;
......@@ -811,12 +811,14 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
err = -EEXIST;
if (dnew->d_inode)
goto dput_and_out;
dest = tfhp->fh_dentry->d_inode;
err = -EPERM;
if (!len)
goto dput_and_out;
dold = tfhp->fh_dentry;
dest = dold->d_inode;
err = -EACCES;
if (nfsd_iscovered(ddir, ffhp->fh_export))
goto dput_and_out;
......@@ -830,7 +832,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
goto dput_and_out;
fh_lock(ffhp);
err = dirp->i_op->link(dest, dirp, dnew);
err = dirp->i_op->link(dold, dirp, dnew);
fh_unlock(ffhp);
if (!err && EX_ISSYNC(ffhp->fh_export)) {
......
......@@ -69,15 +69,16 @@ asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf)
return error;
}
int do_truncate(struct inode *inode, unsigned long length)
int do_truncate(struct dentry *dentry, unsigned long length)
{
struct inode *inode = dentry->d_inode;
int error;
struct iattr newattrs;
down(&inode->i_sem);
newattrs.ia_size = length;
newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
error = notify_change(inode, &newattrs);
error = notify_change(dentry, &newattrs);
if (!error) {
/* truncate virtual mappings of this file */
vmtruncate(inode, length);
......@@ -128,7 +129,7 @@ asmlinkage int sys_truncate(const char * path, unsigned long length)
if (!error) {
if (inode->i_sb && inode->i_sb->dq_op)
inode->i_sb->dq_op->initialize(inode, -1);
error = do_truncate(inode, length);
error = do_truncate(dentry, length);
}
put_write_access(inode);
dput_and_out:
......@@ -161,7 +162,7 @@ asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length)
length<inode->i_size ? length : inode->i_size,
abs(inode->i_size - length));
if (!error)
error = do_truncate(inode, length);
error = do_truncate(dentry, length);
}
unlock_kernel();
return error;
......@@ -214,7 +215,7 @@ asmlinkage int sys_utime(char * filename, struct utimbuf * times)
(error = permission(inode,MAY_WRITE)) != 0)
goto dput_and_out;
}
error = notify_change(inode, &newattrs);
error = notify_change(dentry, &newattrs);
dput_and_out:
dput(dentry);
out:
......@@ -261,7 +262,7 @@ asmlinkage int sys_utimes(char * filename, struct timeval * utimes)
if ((error = permission(inode,MAY_WRITE)) != 0)
goto dput_and_out;
}
error = notify_change(inode, &newattrs);
error = notify_change(dentry, &newattrs);
dput_and_out:
dput(dentry);
out:
......@@ -441,7 +442,7 @@ asmlinkage int sys_fchmod(unsigned int fd, mode_t mode)
mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
err = notify_change(inode, &newattrs);
err = notify_change(dentry, &newattrs);
out:
unlock_kernel();
return err;
......@@ -474,7 +475,7 @@ asmlinkage int sys_chmod(const char * filename, mode_t mode)
mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
error = notify_change(inode, &newattrs);
error = notify_change(dentry, &newattrs);
dput_and_out:
dput(dentry);
......@@ -530,11 +531,11 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
error = -EDQUOT;
if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0))
goto out;
error = notify_change(inode, &newattrs);
error = notify_change(dentry, &newattrs);
if (error)
inode->i_sb->dq_op->transfer(inode, &newattrs, 1);
} else
error = notify_change(inode, &newattrs);
error = notify_change(dentry, &newattrs);
out:
return error;
}
......
......@@ -15,8 +15,8 @@
#include <linux/proc_fs.h>
#include <linux/stat.h>
static int proc_readlink(struct inode *, char *, int);
static struct dentry * proc_follow_link(struct inode *, struct dentry *);
static int proc_readlink(struct dentry *, char *, int);
static struct dentry * proc_follow_link(struct dentry *, struct dentry *);
/*
* PLAN9_SEMANTICS won't work any more: it used an ugly hack that broke
......@@ -60,8 +60,10 @@ struct inode_operations proc_link_inode_operations = {
NULL /* permission */
};
static struct dentry * proc_follow_link(struct inode *inode, struct dentry *base)
static struct dentry * proc_follow_link(struct dentry *dentry,
struct dentry *base)
{
struct inode *inode = dentry->d_inode;
struct task_struct *p;
struct dentry * result;
int ino, pid;
......@@ -73,7 +75,7 @@ static struct dentry * proc_follow_link(struct inode *inode, struct dentry *base
error = permission(inode, MAY_EXEC);
result = ERR_PTR(error);
if (error)
return result;
goto out;
ino = inode->i_ino;
pid = ino >> 16;
......@@ -82,7 +84,7 @@ static struct dentry * proc_follow_link(struct inode *inode, struct dentry *base
p = find_task_by_pid(pid);
result = ERR_PTR(-ENOENT);
if (!p)
return result;
goto out;
switch (ino) {
case PROC_PID_CWD:
......@@ -126,14 +128,15 @@ static struct dentry * proc_follow_link(struct inode *inode, struct dentry *base
break;
}
}
out:
return result;
}
static int proc_readlink(struct inode * inode, char * buffer, int buflen)
static int proc_readlink(struct dentry * dentry, char * buffer, int buflen)
{
int error;
struct dentry * dentry = proc_follow_link(inode, NULL);
dentry = proc_follow_link(dentry, NULL);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
error = -ENOENT;
......
......@@ -65,24 +65,24 @@ struct inode_operations devtree_symlink_inode_operations = {
NULL /* smap */
};
static struct dentry *devtree_follow_link(struct inode *inode,
static struct dentry *devtree_follow_link(struct dentry *dentry,
struct dentry *base)
{
struct proc_dir_entry * de;
char *link;
de = (struct proc_dir_entry *) inode->u.generic_ip;
de = (struct proc_dir_entry *) dentry->inode->u.generic_ip;
link = (char *) de->data;
return lookup_dentry(link, base, 1);
}
static int devtree_readlink(struct inode *inode, char *buffer, int buflen)
static int devtree_readlink(struct dentry *dentry, char *buffer, int buflen)
{
struct proc_dir_entry * de;
char *link;
int linklen;
de = (struct proc_dir_entry *) inode->u.generic_ip;
de = (struct proc_dir_entry *) dentry->inode->u.generic_ip;
link = (char *) de->data;
linklen = strlen(link);
if (linklen > buflen)
......
......@@ -368,7 +368,7 @@ int proc_unregister(struct proc_dir_entry * dir, int ino)
/*
* /proc/self:
*/
static int proc_self_readlink(struct inode * inode, char * buffer, int buflen)
static int proc_self_readlink(struct dentry *dentry, char *buffer, int buflen)
{
int len;
char tmp[30];
......@@ -380,12 +380,12 @@ static int proc_self_readlink(struct inode * inode, char * buffer, int buflen)
return len;
}
static struct dentry * proc_self_follow_link(struct inode *inode, struct dentry *base)
static struct dentry * proc_self_follow_link(struct dentry *dentry,
struct dentry *base)
{
int len;
char tmp[30];
len = sprintf(tmp, "%d", current->pid);
sprintf(tmp, "%d", current->pid);
return lookup_dentry(tmp, base, 1);
}
......
......@@ -391,8 +391,9 @@ romfs_lookup(struct inode *dir, struct dentry *dentry)
*/
static int
romfs_readpage(struct inode * inode, struct page * page)
romfs_readpage(struct dentry * dentry, struct page * page)
{
struct inode *inode = dentry->d_inode;
unsigned long buf;
unsigned long offset, avail, readlen;
int result = -EIO;
......@@ -428,8 +429,9 @@ romfs_readpage(struct inode * inode, struct page * page)
}
static int
romfs_readlink(struct inode *inode, char *buffer, int len)
romfs_readlink(struct dentry *dentry, char *buffer, int len)
{
struct inode *inode = dentry->d_inode;
int mylen;
char buf[ROMFS_MAXFN]; /* XXX dynamic */
......@@ -450,11 +452,12 @@ romfs_readlink(struct inode *inode, char *buffer, int len)
return mylen;
}
static struct dentry *romfs_follow_link(struct inode *inode, struct dentry *base)
static struct dentry *romfs_follow_link(struct dentry *dentry,
struct dentry *base)
{
struct inode *inode = dentry->d_inode;
char *link;
int len, cnt;
struct dentry *dentry;
len = inode->i_size;
......
......@@ -89,7 +89,7 @@ dentry->d_parent->d_name.name, dentry->d_name.name, (int) filp->f_pos);
/*
* Make sure our inode is up-to-date.
*/
result = smb_revalidate_inode(dir);
result = smb_revalidate_inode(dentry);
if (result)
goto out;
/*
......@@ -183,7 +183,7 @@ file->f_dentry->d_name.name);
}
if (server->conn_pid)
error = smb_revalidate_inode(dir);
error = smb_revalidate_inode(dentry);
return error;
}
......@@ -235,7 +235,7 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
#endif
valid = 0;
} else if (!valid)
valid = (smb_revalidate_inode(inode) == 0);
valid = (smb_revalidate_inode(dentry) == 0);
} else
{
/*
......
......@@ -52,24 +52,17 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
* Read a page synchronously.
*/
static int
smb_readpage_sync(struct inode *inode, struct page *page)
smb_readpage_sync(struct dentry *dentry, struct page *page)
{
struct inode *inode = dentry->d_inode;
char *buffer = (char *) page_address(page);
unsigned long offset = page->offset;
struct dentry * dentry = inode->u.smbfs_i.dentry;
int rsize = smb_get_rsize(SMB_SERVER(inode));
int count = PAGE_SIZE;
int result;
clear_bit(PG_error, &page->flags);
result = -EIO;
if (!dentry) {
printk("smb_readpage_sync: no dentry for inode %ld\n",
inode->i_ino);
goto io_error;
}
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_readpage_sync: file %s/%s, count=%d@%ld, rsize=%d\n",
dentry->d_parent->d_name.name, dentry->d_name.name, count, offset, rsize);
......@@ -110,7 +103,7 @@ dentry->d_parent->d_name.name, dentry->d_name.name, result);
}
int
smb_readpage(struct inode *inode, struct page *page)
smb_readpage(struct dentry *dentry, struct page *page)
{
int error;
......@@ -121,7 +114,7 @@ smb_readpage(struct inode *inode, struct page *page)
#endif
set_bit(PG_locked, &page->flags);
atomic_inc(&page->count);
error = smb_readpage_sync(inode, page);
error = smb_readpage_sync(dentry, page);
free_page(page_address(page));
return error;
}
......@@ -131,9 +124,10 @@ smb_readpage(struct inode *inode, struct page *page)
* Offset is the data offset within the page.
*/
static int
smb_writepage_sync(struct inode *inode, struct page *page,
smb_writepage_sync(struct dentry *dentry, struct page *page,
unsigned long offset, unsigned int count)
{
struct inode *inode = dentry->d_inode;
u8 *buffer = (u8 *) page_address(page) + offset;
int wsize = smb_get_wsize(SMB_SERVER(inode));
int result, written = 0;
......@@ -141,8 +135,7 @@ smb_writepage_sync(struct inode *inode, struct page *page,
offset += page->offset;
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_writepage_sync: file %s/%s, count=%d@%ld, wsize=%d\n",
((struct dentry *) inode->u.smbfs_i.dentry)->d_parent->d_name.name,
((struct dentry *) inode->u.smbfs_i.dentry)->d_name.name, count, offset, wsize);
dentry->d_parent->d_name.name, dentry->d_name.name, count, offset, wsize);
#endif
do {
......@@ -185,7 +178,7 @@ printk("smb_writepage_sync: short write, wsize=%d, result=%d\n", wsize, result);
* (for now), and we currently do this synchronously only.
*/
static int
smb_writepage(struct inode *inode, struct page *page)
smb_writepage(struct dentry *dentry, struct page *page)
{
int result;
......@@ -195,20 +188,20 @@ smb_writepage(struct inode *inode, struct page *page)
#endif
set_bit(PG_locked, &page->flags);
atomic_inc(&page->count);
result = smb_writepage_sync(inode, page, 0, PAGE_SIZE);
result = smb_writepage_sync(dentry, page, 0, PAGE_SIZE);
free_page(page_address(page));
return result;
}
static int
smb_updatepage(struct inode *inode, struct page *page, const char *buffer,
smb_updatepage(struct dentry *dentry, struct page *page, const char *buffer,
unsigned long offset, unsigned int count, int sync)
{
unsigned long page_addr = page_address(page);
int result;
pr_debug("SMB: smb_updatepage(%x/%ld %d@%ld, sync=%d)\n",
inode->i_dev, inode->i_ino,
pr_debug("SMBFS: smb_updatepage(%s/%s %d@%ld, sync=%d)\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
count, page->offset+offset, sync);
#ifdef SMBFS_PARANOIA
......@@ -220,7 +213,7 @@ smb_updatepage(struct inode *inode, struct page *page, const char *buffer,
if (copy_from_user((char *) page_addr + offset, buffer, count))
goto bad_fault;
result = smb_writepage_sync(inode, page, offset, count);
result = smb_writepage_sync(dentry, page, offset, count);
out:
free_page(page_addr);
return result;
......@@ -240,7 +233,6 @@ static ssize_t
smb_file_read(struct file * file, char * buf, size_t count, loff_t *ppos)
{
struct dentry * dentry = file->f_dentry;
struct inode * inode = dentry->d_inode;
ssize_t status;
#ifdef SMBFS_DEBUG_VERBOSE
......@@ -249,7 +241,7 @@ dentry->d_parent->d_name.name, dentry->d_name.name,
(unsigned long) count, (unsigned long) *ppos);
#endif
status = smb_revalidate_inode(inode);
status = smb_revalidate_inode(dentry);
if (status)
{
#ifdef SMBFS_PARANOIA
......@@ -261,7 +253,8 @@ dentry->d_parent->d_name.name, dentry->d_name.name, status);
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_file_read: before read, size=%ld, pages=%ld, flags=%x, atime=%ld\n",
inode->i_size, inode->i_nrpages, inode->i_flags, inode->i_atime);
dentry->d_inode->i_size, dentry->d_inode->i_nrpages, dentry->d_inode->i_flags,
dentry->d_inode->i_atime);
#endif
status = generic_file_read(file, buf, count, ppos);
out:
......@@ -272,16 +265,14 @@ static int
smb_file_mmap(struct file * file, struct vm_area_struct * vma)
{
struct dentry * dentry = file->f_dentry;
struct inode * inode = dentry->d_inode;
int status;
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_file_mmap: file %s/%s, address %lu - %lu\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
vma->vm_start, vma->vm_end);
dentry->d_parent->d_name.name, dentry->d_name.name, vma->vm_start, vma->vm_end);
#endif
status = smb_revalidate_inode(inode);
status = smb_revalidate_inode(dentry);
if (status)
{
#ifdef SMBFS_PARANOIA
......@@ -302,16 +293,15 @@ static ssize_t
smb_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
struct dentry * dentry = file->f_dentry;
struct inode * inode = dentry->d_inode;
ssize_t result;
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_file_write: file %s/%s, count=%lu@%lu, pages=%ld\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
(unsigned long) count, (unsigned long) *ppos, inode->i_nrpages);
(unsigned long) count, (unsigned long) *ppos, dentry->d_inode->i_nrpages);
#endif
result = smb_revalidate_inode(inode);
result = smb_revalidate_inode(dentry);
if (result)
{
#ifdef SMBFS_PARANOIA
......@@ -330,7 +320,8 @@ dentry->d_parent->d_name.name, dentry->d_name.name, result);
result = generic_file_write(file, buf, count, ppos);
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_file_write: pos=%ld, size=%ld, mtime=%ld, atime=%ld\n",
(long) file->f_pos, inode->i_size, inode->i_mtime, inode->i_atime);
(long) file->f_pos, dentry->d_inode->i_size, dentry->d_inode->i_mtime,
dentry->d_inode->i_atime);
#endif
}
out:
......
......@@ -186,8 +186,9 @@ printk("smb_invalidate_inodes\n");
* invalidate our local caches.
*/
int
smb_revalidate_inode(struct inode *inode)
smb_revalidate_inode(struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
time_t last_time;
int error = 0;
......@@ -224,8 +225,7 @@ jiffies, inode->u.smbfs_i.oldmtime);
{
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_revalidate: %s/%s changed, old=%ld, new=%ld\n",
((struct dentry *)inode->u.smbfs_i.dentry)->d_parent->d_name.name,
((struct dentry *)inode->u.smbfs_i.dentry)->d_name.name,
dentry->d_parent->d_name.name, dentry->d_name.name,
(long) last_time, (long) inode->i_mtime);
#endif
if (!S_ISDIR(inode->i_mode))
......@@ -492,22 +492,15 @@ smb_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
}
int
smb_notify_change(struct inode *inode, struct iattr *attr)
smb_notify_change(struct dentry *dentry, struct iattr *attr)
{
struct smb_sb_info *server = SMB_SERVER(inode);
struct dentry *dentry = inode->u.smbfs_i.dentry;
struct inode *inode = dentry->d_inode;
struct smb_sb_info *server = server_from_dentry(dentry);
unsigned int mask = (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO);
int error, changed, refresh = 0;
struct smb_fattr fattr;
error = -EIO;
if (!dentry)
{
printk("smb_notify_change: no dentry for inode!\n");
goto out;
}
error = smb_revalidate_inode(inode);
error = smb_revalidate_inode(dentry);
if (error)
goto out;
......
......@@ -20,10 +20,11 @@
* Revalidate the inode. This is required for proper NFS attribute caching.
*/
static __inline__ int
do_revalidate(struct inode *inode)
do_revalidate(struct dentry *dentry)
{
struct inode * inode = dentry->d_inode;
if (inode->i_op && inode->i_op->revalidate)
return inode->i_op->revalidate(inode);
return inode->i_op->revalidate(dentry);
return 0;
}
......@@ -128,10 +129,9 @@ asmlinkage int sys_stat(char * filename, struct __old_kernel_stat * statbuf)
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
struct inode * inode = dentry->d_inode;
error = do_revalidate(inode);
error = do_revalidate(dentry);
if (!error)
error = cp_old_stat(inode, statbuf);
error = cp_old_stat(dentry->d_inode, statbuf);
dput(dentry);
}
......@@ -150,10 +150,9 @@ asmlinkage int sys_newstat(char * filename, struct stat * statbuf)
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
struct inode * inode = dentry->d_inode;
error = do_revalidate(inode);
error = do_revalidate(dentry);
if (!error)
error = cp_new_stat(inode,statbuf);
error = cp_new_stat(dentry->d_inode, statbuf);
dput(dentry);
}
......@@ -177,10 +176,9 @@ asmlinkage int sys_lstat(char * filename, struct __old_kernel_stat * statbuf)
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
struct inode * inode = dentry->d_inode;
error = do_revalidate(inode);
error = do_revalidate(dentry);
if (!error)
error = cp_old_stat(inode, statbuf);
error = cp_old_stat(dentry->d_inode, statbuf);
dput(dentry);
}
......@@ -200,10 +198,9 @@ asmlinkage int sys_newlstat(char * filename, struct stat * statbuf)
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
struct inode * inode = dentry->d_inode;
error = do_revalidate(inode);
error = do_revalidate(dentry);
if (!error)
error = cp_new_stat(inode,statbuf);
error = cp_new_stat(dentry->d_inode, statbuf);
dput(dentry);
}
......@@ -225,11 +222,10 @@ asmlinkage int sys_fstat(unsigned int fd, struct __old_kernel_stat * statbuf)
lock_kernel();
if (fd < NR_OPEN && (f = current->files->fd[fd]) != NULL) {
struct dentry * dentry = f->f_dentry;
struct inode * inode = dentry->d_inode;
err = do_revalidate(inode);
err = do_revalidate(dentry);
if (!err)
err = cp_old_stat(inode,statbuf);
err = cp_old_stat(dentry->d_inode, statbuf);
}
unlock_kernel();
return err;
......@@ -245,11 +241,10 @@ asmlinkage int sys_newfstat(unsigned int fd, struct stat * statbuf)
lock_kernel();
if (fd < NR_OPEN && (f = current->files->fd[fd]) != NULL) {
struct dentry * dentry = f->f_dentry;
struct inode * inode = dentry->d_inode;
err = do_revalidate(inode);
err = do_revalidate(dentry);
if (!err)
err = cp_new_stat(inode,statbuf);
err = cp_new_stat(dentry->d_inode, statbuf);
}
unlock_kernel();
return err;
......@@ -271,9 +266,10 @@ asmlinkage int sys_readlink(const char * path, char * buf, int bufsiz)
struct inode * inode = dentry->d_inode;
error = -EINVAL;
if (inode->i_op && inode->i_op->readlink && !(error = do_revalidate(inode))) {
if (inode->i_op && inode->i_op->readlink &&
!(error = do_revalidate(dentry))) {
UPDATE_ATIME(inode);
error = inode->i_op->readlink(inode,buf,bufsiz);
error = inode->i_op->readlink(dentry, buf, bufsiz);
}
dput(dentry);
}
......
......@@ -873,8 +873,9 @@ void sysv_read_inode(struct inode * inode)
}
/* To avoid inconsistencies between inodes in memory and inodes on disk. */
extern int sysv_notify_change(struct inode *inode, struct iattr *attr)
extern int sysv_notify_change(struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = dentry->d_inode;
int error;
if ((error = inode_change_ok(inode, attr)) != 0)
......
......@@ -20,8 +20,8 @@
#include <asm/uaccess.h>
static int sysv_readlink(struct inode *, char *, int);
static struct dentry *sysv_follow_link(struct inode *, struct dentry *);
static int sysv_readlink(struct dentry *, char *, int);
static struct dentry *sysv_follow_link(struct dentry *, struct dentry *);
/*
* symlinks can't do much...
......@@ -46,8 +46,10 @@ struct inode_operations sysv_symlink_inode_operations = {
NULL /* permission */
};
static struct dentry *sysv_follow_link(struct inode * inode, struct dentry * base)
static struct dentry *sysv_follow_link(struct dentry * dentry,
struct dentry * base)
{
struct inode *inode = dentry->d_inode;
struct buffer_head * bh;
bh = sysv_file_bread(inode, 0, 0);
......@@ -61,8 +63,9 @@ static struct dentry *sysv_follow_link(struct inode * inode, struct dentry * bas
return base;
}
static int sysv_readlink(struct inode * inode, char * buffer, int buflen)
static int sysv_readlink(struct dentry * dentry, char * buffer, int buflen)
{
struct inode *inode = dentry->d_inode;
struct buffer_head * bh;
char * bh_data;
int i;
......
......@@ -19,8 +19,9 @@
extern int ufs_bmap (struct inode *, int);
static int
ufs_readlink(struct inode * inode, char * buffer, int buflen)
ufs_readlink(struct dentry * dentry, char * buffer, int buflen)
{
struct inode * inode = dentry->d_inode;
unsigned long int block;
struct buffer_head * bh = NULL;
char * link;
......@@ -71,8 +72,9 @@ ufs_readlink(struct inode * inode, char * buffer, int buflen)
* XXX - blatantly stolen from minix fs
*/
static struct dentry *
ufs_follow_link(struct inode * inode, struct dentry * base)
ufs_follow_link(struct dentry * dentry, struct dentry * base)
{
struct inode * inode = dentry->d_inode;
unsigned long int block;
struct buffer_head * bh = NULL;
char * link;
......
......@@ -66,6 +66,7 @@ struct dentry {
struct dentry_operations *d_op;
struct super_block * d_sb; /* The root of the dentry tree */
unsigned long d_reftime; /* last time referenced */
void * d_fsdata; /* fs-specific data */
};
struct dentry_operations {
......@@ -73,6 +74,7 @@ struct dentry_operations {
int (*d_hash) (struct dentry *,struct qstr *);
int (*d_compare) (struct dentry *,struct qstr *, struct qstr *);
void (*d_delete)(struct dentry *);
void (*d_release)(struct dentry *);
};
/* the dentry parameter passed to d_hash and d_compare is the parent
......
......@@ -499,9 +499,10 @@ extern int ext2_mkdir (struct inode *,struct dentry *,int);
extern int ext2_rmdir (struct inode *,struct dentry *);
extern int ext2_unlink (struct inode *,struct dentry *);
extern int ext2_symlink (struct inode *,struct dentry *,const char *);
extern int ext2_link (struct inode *, struct inode *, struct dentry *);
extern int ext2_link (struct dentry *, struct inode *, struct dentry *);
extern int ext2_mknod (struct inode *, struct dentry *, int, int);
extern int ext2_rename (struct inode *, struct dentry *,struct inode *, struct dentry *);
extern int ext2_rename (struct inode *, struct dentry *,
struct inode *, struct dentry *);
/* super.c */
extern void ext2_error (struct super_block *, const char *, const char *, ...)
......
......@@ -571,24 +571,25 @@ struct inode_operations {
struct file_operations * default_file_ops;
int (*create) (struct inode *,struct dentry *,int);
int (*lookup) (struct inode *,struct dentry *);
int (*link) (struct inode *,struct inode *,struct dentry *);
int (*link) (struct dentry *,struct inode *,struct dentry *);
int (*unlink) (struct inode *,struct dentry *);
int (*symlink) (struct inode *,struct dentry *,const char *);
int (*mkdir) (struct inode *,struct dentry *,int);
int (*rmdir) (struct inode *,struct dentry *);
int (*mknod) (struct inode *,struct dentry *,int,int);
int (*rename) (struct inode *,struct dentry *,struct inode *,struct dentry *);
int (*readlink) (struct inode *,char *,int);
struct dentry * (*follow_link) (struct inode *, struct dentry *);
int (*readpage) (struct inode *, struct page *);
int (*writepage) (struct inode *, struct page *);
int (*rename) (struct inode *, struct dentry *,
struct inode *, struct dentry *);
int (*readlink) (struct dentry *, char *,int);
struct dentry * (*follow_link) (struct dentry *, struct dentry *);
int (*readpage) (struct dentry *, struct page *);
int (*writepage) (struct dentry *, struct page *);
int (*bmap) (struct inode *,int);
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int);
int (*smap) (struct inode *,int);
int (*updatepage) (struct inode *, struct page *, const char *,
int (*updatepage) (struct dentry *, struct page *, const char *,
unsigned long, unsigned int, int);
int (*revalidate) (struct inode *);
int (*revalidate) (struct dentry *);
};
struct super_operations {
......@@ -596,7 +597,7 @@ struct super_operations {
void (*write_inode) (struct inode *);
void (*put_inode) (struct inode *);
void (*delete_inode) (struct inode *);
int (*notify_change) (struct inode *, struct iattr *);
int (*notify_change) (struct dentry *, struct iattr *);
void (*put_super) (struct super_block *);
void (*write_super) (struct super_block *);
int (*statfs) (struct super_block *, struct statfs *, int);
......@@ -630,7 +631,7 @@ extern void kill_fasync(struct fasync_struct *fa, int sig);
extern char * getname(const char * filename);
extern void putname(char * name);
extern int do_truncate(struct inode *, unsigned long);
extern int do_truncate(struct dentry *, unsigned long);
extern int register_blkdev(unsigned int, const char *, struct file_operations *);
extern int unregister_blkdev(unsigned int major, const char * name);
extern int blkdev_open(struct inode * inode, struct file * filp);
......@@ -710,7 +711,7 @@ extern void sync_dev(kdev_t dev);
extern int fsync_dev(kdev_t dev);
extern void sync_supers(kdev_t dev);
extern int bmap(struct inode * inode,int block);
extern int notify_change(struct inode *, struct iattr *);
extern int notify_change(struct dentry *, struct iattr *);
extern int permission(struct inode * inode,int mask);
extern int get_write_access(struct inode *inode);
extern void put_write_access(struct inode *inode);
......@@ -800,7 +801,7 @@ extern struct buffer_head * breada(kdev_t dev,int block, int size,
extern int brw_page(int, struct page *, kdev_t, int [], int, int);
extern int generic_readpage(struct inode *, struct page *);
extern int generic_readpage(struct dentry *, struct page *);
extern int generic_file_mmap(struct file *, struct vm_area_struct *);
extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *);
extern ssize_t generic_file_write(struct file *, const char*, size_t, loff_t*);
......@@ -831,7 +832,6 @@ extern int file_fsync(struct file *, struct dentry *dir);
extern int inode_change_ok(struct inode *, struct iattr *);
extern void inode_setattr(struct inode *, struct iattr *);
extern int notify_change(struct inode * inode, struct iattr * attr);
/* kludge to get SCSI modules working */
#include <linux/minix_fs.h>
......
......@@ -225,7 +225,7 @@ int get_cluster(struct inode *inode,int cluster);
/* inode.c */
extern int fat_bmap(struct inode *inode,int block);
extern int fat_notify_change(struct inode *,struct iattr *);
extern int fat_notify_change(struct dentry *, struct iattr *);
extern void fat_put_inode(struct inode *inode);
extern void fat_delete_inode(struct inode *inode);
extern void fat_put_super(struct super_block *sb);
......
......@@ -11,9 +11,10 @@
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/nfs.h>
#include <linux/in.h>
#include <linux/sunrpc/debug.h>
#include <linux/nfs.h>
#include <linux/nfs_mount.h>
/*
......@@ -53,11 +54,12 @@
*/
#define NFS_SUPER_MAGIC 0x6969
#define NFS_FH(dentry) ((struct nfs_fh *) ((dentry)->d_fsdata))
#define NFS_DSERVER(dentry) (&(dentry)->d_sb->u.nfs_sb.s_server)
#define NFS_SERVER(inode) (&(inode)->i_sb->u.nfs_sb.s_server)
#define NFS_CLIENT(inode) (NFS_SERVER(inode)->client)
#define NFS_ADDR(inode) (RPC_PEERADDR(NFS_CLIENT(inode)))
#define NFS_CONGESTED(inode) (RPC_CONGESTED(NFS_CLIENT(inode)))
#define NFS_FH(inode) (&(inode)->u.nfs_i.fhandle)
#define NFS_READTIME(inode) ((inode)->u.nfs_i.read_cache_jiffies)
#define NFS_OLDMTIME(inode) ((inode)->u.nfs_i.read_cache_mtime)
......@@ -138,8 +140,8 @@ extern int init_nfs_fs(void);
extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *,
struct nfs_fattr *);
extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
extern int nfs_revalidate(struct inode *);
extern int _nfs_revalidate_inode(struct nfs_server *, struct inode *);
extern int nfs_revalidate(struct dentry *);
extern int _nfs_revalidate_inode(struct nfs_server *, struct dentry *);
/*
* linux/fs/nfs/file.c
......@@ -150,6 +152,7 @@ extern struct inode_operations nfs_file_inode_operations;
* linux/fs/nfs/dir.c
*/
extern struct inode_operations nfs_dir_inode_operations;
extern struct dentry_operations nfs_dentry_operations;
extern void nfs_free_dircache(void);
extern void nfs_invalidate_dircache(struct inode *);
extern void nfs_invalidate_dircache_sb(struct super_block *);
......@@ -162,25 +165,24 @@ extern struct inode_operations nfs_symlink_inode_operations;
/*
* linux/fs/nfs/locks.c
*/
extern int nfs_lock(struct file *file, int cmd, struct file_lock *fl);
extern int nfs_lock(struct file *, int, struct file_lock *);
/*
* linux/fs/nfs/write.c
*/
extern int nfs_writepage(struct inode *, struct page *);
extern int nfs_writepage(struct dentry *, struct page *);
extern int nfs_check_failed_request(struct inode *);
extern int nfs_check_error(struct inode *);
extern int nfs_flush_dirty_pages(struct inode *, pid_t, off_t, off_t);
extern int nfs_truncate_dirty_pages(struct inode *, unsigned long);
extern void nfs_invalidate_pages(struct inode *);
extern int nfs_updatepage(struct inode *, struct page *, const char *,
extern int nfs_updatepage(struct dentry *, struct page *, const char *,
unsigned long, unsigned int, int);
/*
* linux/fs/nfs/read.c
*/
extern int nfs_readpage(struct inode *, struct page *);
extern int nfs_readpage_sync(struct inode *, struct page *);
extern int nfs_readpage(struct dentry *, struct page *);
/*
* linux/fs/mount_clnt.c
......@@ -192,11 +194,12 @@ extern int nfs_mount(struct sockaddr_in *, char *, struct nfs_fh *);
* inline functions
*/
static inline int
nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
if (jiffies - NFS_READTIME(inode) < NFS_ATTRTIMEO(inode))
return 0;
return _nfs_revalidate_inode(server, inode);
return _nfs_revalidate_inode(server, dentry);
}
extern struct nfs_wreq * nfs_failed_requests;
......
......@@ -15,11 +15,6 @@ struct nfs_inode_info {
*/
struct pipe_inode_info pipeinfo;
/*
* The file handle
*/
struct nfs_fh fhandle;
/*
* Various flags
*/
......
......@@ -94,9 +94,9 @@ int smb_ioctl (struct inode *, struct file *, unsigned int, unsigned long);
struct super_block *smb_read_super(struct super_block *, void *, int);
void smb_get_inode_attr(struct inode *, struct smb_fattr *);
void smb_invalidate_inodes(struct smb_sb_info *);
int smb_revalidate_inode(struct inode *);
int smb_revalidate_inode(struct dentry *);
int smb_refresh_inode(struct inode *);
int smb_notify_change(struct inode *, struct iattr *);
int smb_notify_change(struct dentry *, struct iattr *);
unsigned long smb_invent_inos(unsigned long);
struct inode *smb_iget(struct super_block *, struct smb_fattr *);
......
......@@ -260,8 +260,10 @@ static inline void add_to_page_cache(struct page * page,
* that we could use for the cache (if it is 0 we can try to create one,
* this is all overlapped with the IO on the previous page finishing anyway)
*/
static unsigned long try_to_read_ahead(struct inode * inode, unsigned long offset, unsigned long page_cache)
static unsigned long try_to_read_ahead(struct dentry * dentry,
unsigned long offset, unsigned long page_cache)
{
struct inode *inode = dentry->d_inode;
struct page * page;
struct page ** hash;
......@@ -282,7 +284,7 @@ static unsigned long try_to_read_ahead(struct inode * inode, unsigned long offse
*/
page = mem_map + MAP_NR(page_cache);
add_to_page_cache(page, inode, offset, hash);
inode->i_op->readpage(inode, page);
inode->i_op->readpage(dentry, page);
page_cache = 0;
}
release_page(page);
......@@ -445,9 +447,9 @@ static inline int get_max_readahead(struct inode * inode)
return max_readahead[MAJOR(inode->i_dev)][MINOR(inode->i_dev)];
}
static inline unsigned long generic_file_readahead(int reada_ok, struct file * filp, struct inode * inode,
unsigned long ppos, struct page * page,
unsigned long page_cache)
static inline unsigned long generic_file_readahead(int reada_ok,
struct file * filp, struct inode * inode,
unsigned long ppos, struct page * page, unsigned long page_cache)
{
unsigned long max_ahead, ahead;
unsigned long raend;
......@@ -511,7 +513,8 @@ static inline unsigned long generic_file_readahead(int reada_ok, struct file * f
ahead = 0;
while (ahead < max_ahead) {
ahead += PAGE_SIZE;
page_cache = try_to_read_ahead(inode, raend + ahead, page_cache);
page_cache = try_to_read_ahead(filp->f_dentry, raend + ahead,
page_cache);
}
/*
* If we tried to read ahead some pages,
......@@ -559,7 +562,8 @@ static inline unsigned long generic_file_readahead(int reada_ok, struct file * f
ssize_t generic_file_read(struct file * filp, char * buf,
size_t count, loff_t *ppos)
{
struct inode *inode = filp->f_dentry->d_inode;
struct dentry *dentry = filp->f_dentry;
struct inode *inode = dentry->d_inode;
ssize_t error, read;
size_t pos, pgpos, page_cache;
int reada_ok;
......@@ -716,7 +720,7 @@ ssize_t generic_file_read(struct file * filp, char * buf,
if (reada_ok && filp->f_ramax > MIN_READAHEAD)
filp->f_ramax = MIN_READAHEAD;
error = inode->i_op->readpage(inode, page);
error = inode->i_op->readpage(dentry, page);
if (!error)
goto found_page;
release_page(page);
......@@ -728,7 +732,7 @@ ssize_t generic_file_read(struct file * filp, char * buf,
* Try to re-read it _once_. We do this synchronously,
* because this happens only if there were errors.
*/
error = inode->i_op->readpage(inode, page);
error = inode->i_op->readpage(dentry, page);
if (!error) {
wait_on_page(page);
if (PageUptodate(page) && !PageError(page))
......@@ -763,9 +767,10 @@ ssize_t generic_file_read(struct file * filp, char * buf,
*/
static unsigned long filemap_nopage(struct vm_area_struct * area, unsigned long address, int no_share)
{
struct dentry * dentry = area->vm_dentry;
struct inode * inode = dentry->d_inode;
unsigned long offset;
struct page * page, **hash;
struct inode * inode = area->vm_dentry->d_inode;
unsigned long old_page, new_page;
new_page = 0;
......@@ -846,14 +851,14 @@ static unsigned long filemap_nopage(struct vm_area_struct * area, unsigned long
new_page = 0;
add_to_page_cache(page, inode, offset, hash);
if (inode->i_op->readpage(inode, page) != 0)
if (inode->i_op->readpage(dentry, page) != 0)
goto failure;
/*
* Do a very limited read-ahead if appropriate
*/
if (PageLocked(page))
new_page = try_to_read_ahead(inode, offset + PAGE_SIZE, 0);
new_page = try_to_read_ahead(dentry, offset + PAGE_SIZE, 0);
goto found_page;
page_locked_wait:
......@@ -868,7 +873,7 @@ static unsigned long filemap_nopage(struct vm_area_struct * area, unsigned long
* because there really aren't any performance issues here
* and we need to check for errors.
*/
if (inode->i_op->readpage(inode, page) != 0)
if (inode->i_op->readpage(dentry, page) != 0)
goto failure;
wait_on_page(page);
if (PageError(page))
......@@ -1305,7 +1310,8 @@ ssize_t
generic_file_write(struct file *file, const char *buf,
size_t count, loff_t *ppos)
{
struct inode *inode = file->f_dentry->d_inode;
struct dentry *dentry = file->f_dentry;
struct inode *inode = dentry->d_inode;
struct page *page, **hash;
unsigned long page_cache = 0;
unsigned long pgpos, offset;
......@@ -1367,10 +1373,10 @@ generic_file_write(struct file *file, const char *buf,
*/
if (!PageUptodate(page)) {
if (bytes < PAGE_SIZE && pgpos < inode->i_size) {
if (didread < 2)
status = inode->i_op->readpage(inode, page);
else
status = -EIO; /* two tries ... error out */
if (didread < 2)
status = inode->i_op->readpage(dentry,
page);
if (status < 0)
goto done_with_page;
didread++;
......@@ -1380,7 +1386,7 @@ generic_file_write(struct file *file, const char *buf,
}
/* Alright, the page is there. Now update it. */
status = inode->i_op->updatepage(inode, page, buf,
status = inode->i_op->updatepage(dentry, page, buf,
offset, bytes, sync);
done_with_page:
__free_page(page);
......
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