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