--- /dev/null
+
+DE10x
+=====
+
+Memory Addresses:
+
+ SW1 SW2 SW3 SW4
+64K on on on on d0000 dbfff
+ off on on on c0000 cbfff
+ off off on on e0000 ebfff
+
+32K on on off on d8000 dbfff
+ off on off on c8000 cbfff
+ off off off on e8000 ebfff
+
+DBR ROM on on dc000 dffff
+ off on cc000 cffff
+ off off ec000 effff
+
+Note that the 2K mode is set by SW3/SW4 on/off or off/off. Address
+assignment is through the RBSA register.
+
+I/O Address:
+ SW5
+0x300 on
+0x200 off
+
+Remote Boot:
+ SW6
+Disable on
+Enable off
+
+Remote Boot Timeout:
+ SW7
+2.5min on
+30s off
+
+IRQ:
+ SW8 SW9 SW10 SW11 SW12
+2 on off off off off
+3 off on off off off
+4 off off on off off
+5 off off off on off
+7 off off off off on
+
+DE20x
+=====
+
+Memory Size:
+
+ SW3 SW4
+64K on on
+32K off on
+2K on off
+2K off off
+
+Start Addresses:
+
+ SW1 SW2 SW3 SW4
+64K on on on on c0000 cffff
+ on off on on d0000 dffff
+ off on on on e0000 effff
+
+32K on on off off c8000 cffff
+ on off off off d8000 dffff
+ off on off off e8000 effff
+
+Illegal off off - - - -
+
+I/O Address:
+ SW5
+0x300 on
+0x200 off
+
+Remote Boot:
+ SW6
+Disable on
+Enable off
+
+Remote Boot Timeout:
+ SW7
+2.5min on
+30s off
+
+IRQ:
+ SW8 SW9 SW10 SW11 SW12
+5 on off off off off
+9 off on off off off
+10 off off on off off
+11 off off off on off
+15 off off off off on
+
VERSION = 2
PATCHLEVEL = 1
-SUBLEVEL = 77
+SUBLEVEL = 78
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
}
int
-affs_notify_change(struct inode *inode, struct iattr *attr)
+affs_notify_change(struct dentry *dentry, struct iattr *attr)
{
+ struct inode *inode = dentry->d_inode;
int error;
pr_debug("AFFS: notify_change(%lu,0x%x)\n",inode->i_ino,attr->ia_valid);
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
-static int affs_readlink(struct inode *, char *, int);
-static struct dentry *affs_follow_link(struct inode *inode, struct dentry *base);
+static int affs_readlink(struct dentry *, char *, int);
+static struct dentry *affs_follow_link(struct dentry *dentry, struct dentry *base);
struct inode_operations affs_symlink_inode_operations = {
NULL, /* no file-operations */
};
static int
-affs_readlink(struct inode *inode, char *buffer, int buflen)
+affs_readlink(struct inode *dentry, char *buffer, int buflen)
{
+ struct inode *inode = dentry->d_inode;
struct buffer_head *bh;
struct slink_front *lf;
int i, j;
}
static struct dentry *
-affs_follow_link(struct inode *inode, struct dentry *base)
+affs_follow_link(struct dentry *dentry, struct dentry *base)
{
+ struct inode *inode = dentry->d_inode;
struct buffer_head *bh;
struct slink_front *lf;
char *buffer;
mark_inode_dirty(inode);
}
-int notify_change(struct inode * inode, struct iattr * attr)
+int notify_change(struct dentry * dentry, struct iattr * attr)
{
+ struct inode *inode = dentry->d_inode;
int error;
time_t now = CURRENT_TIME;
unsigned int ia_valid = attr->ia_valid;
if (!(ia_valid & ATTR_MTIME_SET))
attr->ia_mtime = now;
- if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->notify_change)
- return inode->i_sb->s_op->notify_change(inode, attr);
-
- error = inode_change_ok(inode, attr);
- if (!error)
- inode_setattr(inode, attr);
+ if (inode->i_sb && inode->i_sb->s_op &&
+ inode->i_sb->s_op->notify_change)
+ error = inode->i_sb->s_op->notify_change(dentry, attr);
+ else {
+ error = inode_change_ok(inode, attr);
+ if (!error)
+ inode_setattr(inode, attr);
+ }
return error;
}
#include <linux/sched.h>
#include "autofs_i.h"
-static int autofs_readlink(struct inode *inode, char *buffer, int buflen)
+static int autofs_readlink(struct dentry *dentry, char *buffer, int buflen)
{
struct autofs_symlink *sl;
int len;
- sl = (struct autofs_symlink *)inode->u.generic_ip;
+ sl = (struct autofs_symlink *)dentry->d_inode->u.generic_ip;
len = sl->len;
if (len > buflen) len = buflen;
- copy_to_user(buffer,sl->data,len);
+ copy_to_user(buffer, sl->data, len);
return len;
}
-static struct dentry * autofs_follow_link(struct inode *inode, struct dentry *base)
+static struct dentry * autofs_follow_link(struct dentry *dentry,
+ struct dentry *base)
{
struct autofs_symlink *sl;
- sl = (struct autofs_symlink *)inode->u.generic_ip;
+ sl = (struct autofs_symlink *)dentry->d_inode->u.generic_ip;
return lookup_dentry(sl->data, base, 1);
}
/*
* The follow_symlink operation must dput() the base.
*/
-static struct dentry * bad_follow_link(struct inode * ino, struct dentry *base)
+static struct dentry * bad_follow_link(struct dentry *dent, struct dentry *base)
{
dput(base);
return ERR_PTR(-EIO);
* mark_buffer_uptodate() functions propagate buffer state into the
* page struct once IO has completed.
*/
-int generic_readpage(struct inode * inode, struct page * page)
+int generic_readpage(struct dentry * dentry, struct page * page)
{
+ struct inode *inode = dentry->d_inode;
unsigned long block;
int *p, nr[PAGE_SIZE/512];
int i;
#include <linux/coda_cache.h>
/* file operations */
-static int coda_readpage(struct inode * inode, struct page * page);
-static ssize_t coda_file_read(struct file *f, char *buf, size_t count, loff_t *off);
-static ssize_t coda_file_write(struct file *f, const char *buf, size_t count, loff_t *off);
-static int coda_file_mmap(struct file * file, struct vm_area_struct * vma);
+static int coda_readpage(struct dentry *, struct page *);
+static ssize_t coda_file_read(struct file *, char *, size_t, loff_t *);
+static ssize_t coda_file_write(struct file *, const char *, size_t, loff_t *);
+static int coda_file_mmap(struct file *, struct vm_area_struct *);
/* exported from this file */
int coda_fsync(struct file *, struct dentry *dentry);
};
/* File file operations */
-static int coda_readpage(struct inode * inode, struct page * page)
+static int coda_readpage(struct dentry *dentry, struct page * page)
{
- struct inode *open_inode;
+ struct inode *open_inode, *inode = dentry->d_inode;
struct cnode *cnp;
ENTRY;
CDEBUG(D_INODE, "coda ino: %ld, cached ino %ld, page offset: %lx\n", inode->i_ino, open_inode->i_ino, page->offset);
+ /* N.B. This needs the dentry for open_inode */
generic_readpage(open_inode, page);
EXIT;
return 0;
/* VFS super_block ops */
static struct super_block *coda_read_super(struct super_block *, void *, int);
static void coda_read_inode(struct inode *);
-static int coda_notify_change(struct inode *inode, struct iattr *attr);
+static int coda_notify_change(struct dentry *, struct iattr *);
static void coda_put_inode(struct inode *);
static void coda_delete_inode(struct inode *);
static void coda_put_super(struct super_block *);
printk("coda_read_super: rootinode is %ld dev %d\n",
root->i_ino, root->i_dev);
sbi->sbi_root = root;
+ /* N.B. check this for failure */
sb->s_root = d_alloc_root(root, NULL);
unlock_super(sb);
EXIT;
error:
EXIT;
- MOD_DEC_USE_COUNT;
if (sbi) {
sbi->sbi_vcomm = NULL;
sbi->sbi_root = NULL;
coda_cnode_free(ITOC(root));
}
sb->s_dev = 0;
+ MOD_DEC_USE_COUNT;
return NULL;
}
EXIT;
}
-static int coda_notify_change(struct inode *inode, struct iattr *iattr)
+static int coda_notify_change(struct dentry *dentry, struct iattr *iattr)
{
+ struct inode *inode = dentry->d_inode;
struct cnode *cnp;
struct coda_vattr vattr;
int error;
#include <linux/coda_cnode.h>
#include <linux/coda_cache.h>
-static int coda_readlink(struct inode *inode, char *buffer, int length);
-static struct dentry *coda_follow_link(struct inode *, struct dentry *);
+static int coda_readlink(struct dentry *dentry, char *buffer, int length);
+static struct dentry *coda_follow_link(struct dentry *, struct dentry *);
struct inode_operations coda_symlink_inode_operations = {
NULL, /* no file-operations */
NULL /* revalidate */
};
-static int coda_readlink(struct inode *inode, char *buffer, int length)
+static int coda_readlink(struct inode *dentry, char *buffer, int length)
{
+ struct inode *inode = dentry->d_inode;
int len;
int error;
char *buf;
return error;
}
-static struct dentry *coda_follow_link(struct inode *inode,
- struct dentry *base)
+static struct dentry *coda_follow_link(struct dentry *dentry,
+ struct dentry *base)
{
+ struct inode *inode = dentry->d_inode;
int error;
struct cnode *cnp;
unsigned int len;
- char mem[CFS_MAXPATHLEN];
char *path;
+ char mem[CFS_MAXPATHLEN]; /* N.B. too big for the stack? */
ENTRY;
CDEBUG(D_INODE, "(%x/%ld)\n", inode->i_dev, inode->i_ino);
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);
}
dentry->d_name.len = name->len;
dentry->d_name.hash = name->hash;
dentry->d_op = NULL;
+ dentry->d_fsdata = NULL;
return dentry;
}
return ext2_update_inode (inode, 1);
}
-int ext2_notify_change(struct inode *inode, struct iattr *iattr)
+int ext2_notify_change(struct dentry *dentry, struct iattr *iattr)
{
+ struct inode *inode = dentry->d_inode;
int retval;
unsigned int flags;
+ retval = -EPERM;
if ((iattr->ia_attr_flags &
(ATTR_FLAG_APPEND | ATTR_FLAG_IMMUTABLE)) ^
(inode->u.ext2_i.i_flags &
(EXT2_APPEND_FL | EXT2_IMMUTABLE_FL))) {
if (securelevel > 0 || !fsuser())
- return -EPERM;
- } else
- if ((current->fsuid != inode->i_uid) && !fsuser())
- return -EPERM;
+ goto out;
+ } else if ((current->fsuid != inode->i_uid) && !fsuser())
+ goto out;
- if ((retval = inode_change_ok(inode, iattr)) != 0)
- return retval;
+ retval = inode_change_ok(inode, iattr);
+ if (retval != 0)
+ goto out;
inode_setattr(inode, iattr);
inode->u.ext2_i.i_flags &= ~EXT2_IMMUTABLE_FL;
}
mark_inode_dirty(inode);
-
- return 0;
+out:
+ return retval;
}
goto out;
}
-int ext2_link (struct inode * inode, struct inode * dir, struct dentry *dentry)
+int ext2_link (struct dentry * old_dentry,
+ struct inode * dir, struct dentry *dentry)
{
+ struct inode *inode = old_dentry->d_inode;
struct ext2_dir_entry * de;
struct buffer_head * bh;
int err;
#include <linux/mm.h>
#include <linux/stat.h>
-static int ext2_readlink (struct inode *, char *, int);
-static struct dentry *ext2_follow_link(struct inode *, struct dentry *);
+static int ext2_readlink (struct dentry *, char *, int);
+static struct dentry *ext2_follow_link(struct dentry *, struct dentry *);
/*
* symlinks can't do much...
NULL /* smap */
};
-static struct dentry * ext2_follow_link(struct inode * inode, struct dentry *base)
+static struct dentry * ext2_follow_link(struct dentry * dentry,
+ struct dentry *base)
{
- int error;
+ struct inode *inode = dentry->d_inode;
struct buffer_head * bh = NULL;
+ int error;
char * link;
link = (char *) inode->u.ext2_i.i_data;
return base;
}
-static int ext2_readlink (struct inode * inode, char * buffer, int buflen)
+static int ext2_readlink (struct dentry * dentry, char * buffer, int buflen)
{
+ struct inode *inode = dentry->d_inode;
struct buffer_head * bh = NULL;
char * link;
int i;
}
-int fat_notify_change(struct inode * inode,struct iattr * attr)
+int fat_notify_change(struct dentry * dentry, struct iattr * attr)
{
- struct super_block *sb = inode->i_sb;
+ struct super_block *sb = dentry->d_sb;
+ struct inode *inode = dentry->d_inode;
int error;
error = inode_change_ok(inode, attr);
#include <asm/uaccess.h>
-static int isofs_readlink(struct inode *, char *, int);
-static struct dentry * isofs_follow_link(struct inode * inode, struct dentry *base);
+static int isofs_readlink(struct dentry *, char *, int);
+static struct dentry * isofs_follow_link(struct dentry *, struct dentry *);
/*
* symlinks can't do much...
NULL /* permission */
};
-static int isofs_readlink(struct inode * inode, char * buffer, int buflen)
+static int isofs_readlink(struct dentry * dentry, char * buffer, int buflen)
{
char * pnt;
int i;
if (buflen > 1023)
buflen = 1023;
- pnt = get_rock_ridge_symlink(inode);
+ pnt = get_rock_ridge_symlink(dentry->d_inode);
if (!pnt)
return 0;
return i;
}
-static struct dentry * isofs_follow_link(struct inode * inode, struct dentry *base)
+static struct dentry * isofs_follow_link(struct dentry * dentry,
+ struct dentry *base)
{
char * pnt;
- pnt = get_rock_ridge_symlink(inode);
-
+ pnt = get_rock_ridge_symlink(dentry->d_inode);
if(!pnt) {
dput(base);
return ERR_PTR(-ELOOP);
memset(argp, 0, sizeof(*argp));
argp->cookie = nlm_cookie++;
argp->state = nsm_local_state;
- lock->fh = *NFS_FH(fl->fl_file->f_dentry->d_inode);
+ lock->fh = *NFS_FH(fl->fl_file->f_dentry);
lock->caller = system_utsname.nodename;
lock->oh.data = req->a_owner;
lock->oh.len = sprintf(req->a_owner, "%d@%s",
#include <asm/uaccess.h>
-static int minix_readlink(struct inode *, char *, int);
-static struct dentry *minix_follow_link(struct inode *, struct dentry *);
+static int minix_readlink(struct dentry *, char *, int);
+static struct dentry *minix_follow_link(struct dentry *, struct dentry *);
/*
* symlinks can't do much...
NULL /* permission */
};
-static struct dentry * minix_follow_link(struct inode * inode, struct dentry * base)
+static struct dentry * minix_follow_link(struct dentry * dentry,
+ struct dentry * base)
{
+ struct inode *inode = dentry->d_inode;
struct buffer_head * bh;
bh = minix_bread(inode, 0, 0);
return base;
}
-static int minix_readlink(struct inode * inode, char * buffer, int buflen)
+static int minix_readlink(struct dentry * dentry, char * buffer, int buflen)
{
struct buffer_head * bh;
int i;
if (buflen > 1023)
buflen = 1023;
- bh = minix_bread(inode, 0, 0);
+ bh = minix_bread(dentry->d_inode, 0, 0);
if (!bh)
return 0;
i = 0;
}
/*
- * This is called when everything else fails, and we actually have
- * to go to the low-level filesystem to find out what we should do..
- *
- * We get the directory semaphore, and after getting that we also
- * make sure that nobody added the entry to the dcache in the meantime..
+ * "." and ".." are special - ".." especially so because it has to be able
+ * to know about the current root directory and parent relationships
*/
-static struct dentry * real_lookup(struct dentry * parent, struct qstr * name)
+static struct dentry * reserved_lookup(struct dentry * parent, struct qstr * name)
{
- struct dentry * result;
- struct inode *dir = parent->d_inode;
+ struct dentry *result = NULL;
+ if (name->name[0] == '.') {
+ switch (name->len) {
+ default:
+ break;
+ case 2:
+ if (name->name[1] != '.')
+ break;
- down(&dir->i_sem);
- result = d_lookup(parent, name);
- if (!result) {
- struct dentry * dentry = d_alloc(parent, name);
- result = ERR_PTR(-ENOMEM);
- if (dentry) {
- int error = dir->i_op->lookup(dir, dentry);
- result = dentry;
- if (error) {
- dput(dentry);
- result = ERR_PTR(error);
- }
+ if (parent != current->fs->root)
+ parent = parent->d_covers->d_parent;
+ /* fallthrough */
+ case 1:
+ result = parent;
}
}
- up(&dir->i_sem);
- return result;
+ return dget(result);
}
/*
}
/*
- * "." and ".." are special - ".." especially so because it has to be able
- * to know about the current root directory and parent relationships
+ * This is called when everything else fails, and we actually have
+ * to go to the low-level filesystem to find out what we should do..
+ *
+ * We get the directory semaphore, and after getting that we also
+ * make sure that nobody added the entry to the dcache in the meantime..
*/
-static struct dentry * reserved_lookup(struct dentry * parent, struct qstr * name)
+static struct dentry * real_lookup(struct dentry * parent, struct qstr * name)
{
- struct dentry *result = NULL;
- if (name->name[0] == '.') {
- switch (name->len) {
- default:
- break;
- case 2:
- if (name->name[1] != '.')
- break;
+ struct dentry * result;
+ struct inode *dir = parent->d_inode;
- if (parent != current->fs->root)
- parent = parent->d_covers->d_parent;
- /* fallthrough */
- case 1:
- result = parent;
+ down(&dir->i_sem);
+ /*
+ * First re-do the cached lookup just in case it was created
+ * while we waited for the directory semaphore..
+ *
+ * FIXME! This could use version numbering or similar to
+ * avoid unnecessary cache lookups.
+ */
+ result = cached_lookup(parent, name);
+ if (!result) {
+ struct dentry * dentry = d_alloc(parent, name);
+ result = ERR_PTR(-ENOMEM);
+ if (dentry) {
+ int error = dir->i_op->lookup(dir, dentry);
+ result = dentry;
+ if (error) {
+ dput(dentry);
+ result = ERR_PTR(error);
+ }
}
}
- return dget(result);
+ up(&dir->i_sem);
+ return result;
}
static struct dentry * do_follow_link(struct dentry *base, struct dentry *dentry)
current->link_count++;
/* This eats the base */
- result = inode->i_op->follow_link(inode, base);
+ result = inode->i_op->follow_link(dentry, base);
current->link_count--;
dput(dentry);
return result;
if (inode->i_sb && inode->i_sb->dq_op)
inode->i_sb->dq_op->initialize(inode, -1);
- error = do_truncate(inode, 0);
+ error = do_truncate(dentry, 0);
}
put_write_access(inode);
if (error)
if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op)
dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1);
- error = dir->d_inode->i_op->link(inode, dir->d_inode, new_dentry);
+ error = dir->d_inode->i_op->link(old_dentry, dir->d_inode, new_dentry);
exit_lock:
unlock_dir(dir);
/*
* Dentry operations routines
*/
-static int ncp_lookup_validate(struct dentry *);
-static void ncp_delete_dentry(struct dentry *);
+static int ncp_lookup_validate(struct dentry *);
static int ncp_hash_dentry(struct dentry *, struct qstr *);
static int ncp_compare_dentry (struct dentry *, struct qstr *, struct qstr *);
+static void ncp_delete_dentry(struct dentry *);
static struct dentry_operations ncp_dentry_operations =
{
*/
#define tolower(c) (((c) >= 'A' && (c) <= 'Z') ? (c)-('A'-'a') : (c))
-
+/*
+ * Note: leave the hash unchanged if the directory
+ * is case-sensitive.
+ */
static int
ncp_hash_dentry(struct dentry *dentry, struct qstr *this)
{
- unsigned long hash;
- int i;
-
- hash = init_name_hash();
- for (i=0; i<this->len ; i++)
- hash = partial_name_hash(tolower(this->name[i]),hash);
- this->hash = end_name_hash(hash);
-
- return 0;
+ unsigned long hash;
+ int i;
+
+ if (!ncp_case_sensitive(dentry->d_inode)) {
+ hash = init_name_hash();
+ for (i=0; i<this->len ; i++)
+ hash = partial_name_hash(tolower(this->name[i]),hash);
+ this->hash = end_name_hash(hash);
+ }
+ return 0;
}
static int
*/
ino_t ncp_invent_inos(unsigned long n)
{
- static ino_t ino = 1;
+ static ino_t ino = 2;
if (ino + 2*n < ino)
{
/* wrap around */
- ino += n;
+ ino = 2;
}
ino += n;
return ino;
}
-/*
- * Check whether a dentry already exists for the given name,
- * and return the inode number if it has an inode. This is
- * needed to keep getcwd() working.
- */
-static ino_t
-find_inode_number(struct dentry *dir, struct qstr *name)
-{
- unsigned long hash;
- int i;
- struct dentry * dentry;
- ino_t ino = 0;
-
- hash = init_name_hash();
- for (i=0; i<name->len ; i++)
- hash = partial_name_hash(tolower(name->name[i]),hash);
- name->hash = end_name_hash(hash);
-
- dentry = d_lookup(dir, name);
- if (dentry)
- {
- if (dentry->d_inode)
- ino = dentry->d_inode->i_ino;
- dput(dentry);
- }
- return ino;
-}
-
static inline int
ncp_single_volume(struct ncp_server *server)
{
#include <linux/fcntl.h>
#include <linux/stat.h>
#include <linux/mm.h>
-#include <linux/ncp_fs.h>
#include <linux/locks.h>
-#include "ncplib_kernel.h"
#include <linux/malloc.h>
+#include <linux/ncp_fs.h>
+#include "ncplib_kernel.h"
+
static inline int min(int a, int b)
{
return a < b ? a : b;
result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
NULL, NULL, OC_MODE_OPEN,
0, AR_READ, &finfo);
- if (!result) {
+ if (result) {
#ifdef NCPFS_PARANOIA
printk(KERN_DEBUG "ncp_make_open: failed, result=%d\n", result);
#endif
#ifdef NCPFS_PARANOIA
printk(KERN_DEBUG "ncp_make_open: file open, access=%x\n", access);
#endif
- if (((right == O_RDONLY) && ((access == O_RDONLY)
- || (access == O_RDWR)))
- || ((right == O_WRONLY) && ((access == O_WRONLY)
- || (access == O_RDWR)))
- || ((right == O_RDWR) && (access == O_RDWR)))
+ if (access == right || access == O_RDWR)
error = 0;
out_unlock:
}
}
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = inode->i_atime = CURRENT_TIME;
file->f_pos = pos;
static void ncp_read_inode(struct inode *);
static void ncp_put_inode(struct inode *);
static void ncp_delete_inode(struct inode *);
-static int ncp_notify_change(struct inode *, struct iattr *);
+static int ncp_notify_change(struct dentry *, struct iattr *);
static void ncp_put_super(struct super_block *);
static int ncp_statfs(struct super_block *, struct statfs *, int);
i->entryName[0] = '\0';
root->finfo.opened= 0;
- info->ino = 1;
+ info->ino = 2; /* tradition */
info->nw_info = root->finfo;
}
ncp_unlock_server(server);
close_fp(server->ncp_filp);
- kill_proc(server->m.wdog_pid, SIGTERM, 0);
+ kill_proc(server->m.wdog_pid, SIGTERM, 1);
ncp_kfree_s(server->packet, server->packet_size);
return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
}
-static int ncp_notify_change(struct inode *inode, struct iattr *attr)
+static int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
{
+ struct inode *inode = dentry->d_inode;
int result = 0;
int info_mask;
struct nw_modify_dos_info info;
- if (!ncp_conn_valid(NCP_SERVER(inode))) {
- return -EIO;
- }
- if ((result = inode_change_ok(inode, attr)) < 0)
- return result;
+ result = -EIO;
+ if (!ncp_conn_valid(NCP_SERVER(inode)))
+ goto out;
+
+ result = inode_change_ok(inode, attr);
+ if (result < 0)
+ goto out;
+ result = -EPERM;
if (((attr->ia_valid & ATTR_UID) &&
(attr->ia_uid != NCP_SERVER(inode)->m.uid)))
- return -EPERM;
+ goto out;
if (((attr->ia_valid & ATTR_GID) &&
(attr->ia_uid != NCP_SERVER(inode)->m.gid)))
- return -EPERM;
+ goto out;
if (((attr->ia_valid & ATTR_MODE) &&
(attr->ia_mode &
~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
- return -EPERM;
+ goto out;
info_mask = 0;
memset(&info, 0, sizeof(info));
if ((attr->ia_valid & ATTR_SIZE) != 0) {
int written;
- DPRINTK(KERN_DEBUG "ncpfs: trying to change size to %ld\n", attr->ia_size);
+ DPRINTK(KERN_DEBUG "ncpfs: trying to change size to %ld\n",
+ attr->ia_size);
if ((result = ncp_make_open(inode, O_RDWR)) < 0) {
return -EACCES;
closing the file */
result = ncp_make_closed(inode);
}
- /*
- * We need a dentry here ...
- */
- /* ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode); */
-
+ ncp_invalid_dir_cache(dentry->d_parent->d_inode);
+out:
return result;
}
static int nfs_rmdir(struct inode *, struct dentry *);
static int nfs_unlink(struct inode *, struct dentry *);
static int nfs_symlink(struct inode *, struct dentry *, const char *);
-static int nfs_link(struct inode *, struct inode *, struct dentry *);
+static int nfs_link(struct dentry *, struct inode *, struct dentry *);
static int nfs_mknod(struct inode *, struct dentry *, int, int);
static int nfs_rename(struct inode *, struct dentry *,
struct inode *, struct dentry *);
static int
nfs_dir_open(struct inode *dir, struct file *file)
{
- dfprintk(VFS, "NFS: nfs_dir_open(%x/%ld)\n", dir->i_dev, dir->i_ino);
- return nfs_revalidate_inode(NFS_SERVER(dir), dir);
+ struct dentry *dentry = file->f_dentry;
+
+ dfprintk(VFS, "NFS: nfs_dir_open(%s/%s)\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name);
+ return nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
}
static ssize_t
static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct dentry *dentry = filp->f_dentry;
+ struct inode *inode = dentry->d_inode;
static struct wait_queue *readdir_wait = NULL;
struct wait_queue **waitp = NULL;
struct nfs_dirent *cache, *free;
__u32 *entry;
char *name, *start;
- dfprintk(VFS, "NFS: nfs_readdir(%x/%ld)\n", inode->i_dev, inode->i_ino);
+ dfprintk(VFS, "NFS: nfs_readdir(%s/%s)\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name);
+ result = -EBADF;
if (!inode || !S_ISDIR(inode->i_mode)) {
printk("nfs_readdir: inode is NULL or not a directory\n");
- return -EBADF;
+ goto out;
}
- if ((result = nfs_revalidate_inode(NFS_SERVER(inode), inode)) < 0)
- return result;
+ result = nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
+ if (result < 0)
+ goto out;
/*
* Try to find the entry in the cache
goto done;
}
- result = nfs_proc_readdir(NFS_SERVER(inode), NFS_FH(inode),
+ result = nfs_proc_readdir(NFS_SERVER(inode), NFS_FH(dentry),
cookie, PAGE_SIZE, cache->entry);
if (result <= 0)
goto done;
wake_up(&cache->wait);
wake_up(&readdir_wait);
+out:
return result;
}
#endif
}
-static struct dentry_operations nfs_dentry_operations = {
+/*
+ * Called when the dentry is being freed to release private memory.
+ */
+static void nfs_dentry_release(struct dentry *dentry)
+{
+ if (dentry->d_fsdata)
+ kfree(dentry->d_fsdata);
+}
+
+struct dentry_operations nfs_dentry_operations = {
nfs_lookup_revalidate, /* d_validate(struct dentry *) */
- 0, /* d_hash */
- 0, /* d_compare */
- nfs_dentry_delete /* d_delete(struct dentry *) */
+ NULL, /* d_hash */
+ NULL, /* d_compare */
+ nfs_dentry_delete, /* d_delete(struct dentry *) */
+ nfs_dentry_release /* d_release(struct dentry *) */
};
/*
}
}
+static void nfs_set_fh(struct dentry *dentry, struct nfs_fh *fhandle)
+{
+ *((struct nfs_fh *) dentry->d_fsdata) = *fhandle;
+}
+
static int nfs_lookup(struct inode *dir, struct dentry * dentry)
{
- int len = dentry->d_name.len;
struct inode *inode;
int error;
struct nfs_fh fhandle;
struct nfs_fattr fattr;
- dfprintk(VFS, "NFS: lookup(%x/%ld, %.*s)\n",
- dir->i_dev, dir->i_ino, len, dentry->d_name.name);
+ dfprintk(VFS, "NFS: lookup(%s/%s)\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name);
if (!dir || !S_ISDIR(dir->i_mode)) {
printk("nfs_lookup: inode is NULL or not a directory\n");
}
error = -ENAMETOOLONG;
- if (len > NFS_MAXNAMLEN)
+ if (dentry->d_name.len > NFS_MAXNAMLEN)
goto out;
- error = nfs_proc_lookup(NFS_SERVER(dir), NFS_FH(dir),
+ error = -ENOMEM;
+ if (!dentry->d_fsdata) {
+ dentry->d_fsdata = kmalloc(sizeof(struct nfs_fh), GFP_KERNEL);
+ if (!dentry->d_fsdata)
+ goto out;
+ }
+ dentry->d_op = &nfs_dentry_operations;
+
+ error = nfs_proc_lookup(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
dentry->d_name.name, &fhandle, &fattr);
inode = NULL;
if (error == -ENOENT)
goto no_entry;
if (!error) {
error = -EACCES;
- inode = nfs_fhget(dir->i_sb, &fhandle, &fattr);
+ nfs_set_fh(dentry, &fhandle);
+ inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr);
if (inode) {
#ifdef NFS_PARANOIA
if (inode->i_count > (S_ISDIR(inode->i_mode) ? 1 : inode->i_nlink))
inode->i_ino, inode->i_count, inode->i_nlink);
#endif
no_entry:
- dentry->d_op = &nfs_dentry_operations;
d_add(dentry, inode);
nfs_renew_times(dentry);
error = 0;
struct inode *inode;
int error = -EACCES;
+ nfs_set_fh(dentry, fhandle);
inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
if (inode) {
#ifdef NFS_PARANOIA
* Invalidate the dir cache before the operation to avoid a race.
*/
nfs_invalidate_dircache(dir);
- error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir),
+ error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
dentry->d_name.name, &sattr, &fhandle, &fattr);
if (!error)
error = nfs_instantiate(dentry, &fhandle, &fattr);
sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
nfs_invalidate_dircache(dir);
- error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir),
+ error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
dentry->d_name.name, &sattr, &fhandle, &fattr);
if (!error)
error = nfs_instantiate(dentry, &fhandle, &fattr);
sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
nfs_invalidate_dircache(dir);
- error = nfs_proc_mkdir(NFS_SERVER(dir), NFS_FH(dir),
+ error = nfs_proc_mkdir(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
dentry->d_name.name, &sattr, &fhandle, &fattr);
/*
dentry->d_inode->i_nlink --;
d_delete(dentry);
nfs_invalidate_dircache(dir);
- error = nfs_proc_rmdir(NFS_SERVER(dir),
- NFS_FH(dir), dentry->d_name.name);
+ error = nfs_proc_rmdir(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
+ dentry->d_name.name);
if (!error) {
if (rehash)
d_add(dentry, NULL);
nfs_invalidate_dircache(dir);
error = nfs_proc_rename(NFS_SERVER(dir),
- NFS_FH(dir), dentry->d_name.name,
- NFS_FH(dir), silly);
+ NFS_FH(dentry->d_parent), dentry->d_name.name,
+ NFS_FH(dentry->d_parent), silly);
if (!error) {
nfs_renew_times(dentry);
d_move(dentry, sdentry);
d_delete(dentry);
}
nfs_invalidate_dircache(dir);
- error = nfs_proc_remove(NFS_SERVER(dir),
- NFS_FH(dir), dentry->d_name.name);
+ error = nfs_proc_remove(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
+ dentry->d_name.name);
/*
* Rehash the negative dentry if the operation succeeded.
*/
*/
d_drop(dentry);
nfs_invalidate_dircache(dir);
- error = nfs_proc_symlink(NFS_SERVER(dir), NFS_FH(dir),
+ error = nfs_proc_symlink(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
dentry->d_name.name, symname, &sattr);
if (!error) {
nfs_renew_times(dentry->d_parent);
}
static int
-nfs_link(struct inode *inode, struct inode *dir, struct dentry *dentry)
+nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
{
+ struct inode *inode = old_dentry->d_inode;
int error;
- dfprintk(VFS, "NFS: link(%x/%ld -> %x/%ld, %s)\n",
- inode->i_dev, inode->i_ino,
- dir->i_dev, dir->i_ino, dentry->d_name.name);
+ dfprintk(VFS, "NFS: link(%s/%s -> %s/%s)\n",
+ old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
+ dentry->d_parent->d_name.name, dentry->d_name.name);
if (!dir || !S_ISDIR(dir->i_mode)) {
printk("nfs_link: dir is NULL or not a directory\n");
if (dentry->d_name.len > NFS_MAXNAMLEN)
goto out;
+ /*
+ * Drop the dentry in advance to force a new lookup.
+ * Since nfs_proc_link doesn't return a filehandle,
+ * we can't use the existing dentry.
+ */
+ d_drop(dentry);
nfs_invalidate_dircache(dir);
- error = nfs_proc_link(NFS_SERVER(inode), NFS_FH(inode), NFS_FH(dir),
- dentry->d_name.name);
+ error = nfs_proc_link(NFS_DSERVER(old_dentry), NFS_FH(old_dentry),
+ NFS_FH(dentry->d_parent), dentry->d_name.name);
if (!error) {
- inode->i_count ++;
- inode->i_nlink ++; /* no need to wait for nfs_refresh_inode() */
- d_instantiate(dentry, inode);
+ /*
+ * Update the link count immediately, as some apps
+ * (e.g. pine) test this after making a link.
+ */
+ inode->i_nlink++;
}
out:
return error;
nfs_invalidate_dircache(new_dir);
nfs_invalidate_dircache(old_dir);
- error = nfs_proc_rename(NFS_SERVER(old_dir),
- NFS_FH(old_dir), old_dentry->d_name.name,
- NFS_FH(new_dir), new_dentry->d_name.name);
+ error = nfs_proc_rename(NFS_DSERVER(old_dentry),
+ NFS_FH(old_dentry->d_parent), old_dentry->d_name.name,
+ NFS_FH(new_dentry->d_parent), new_dentry->d_name.name);
if (!error) {
/* Update the dcache if needed */
if (rehash)
static ssize_t
nfs_file_read(struct file * file, char * buf, size_t count, loff_t *ppos)
{
- struct inode * inode = file->f_dentry->d_inode;
+ struct dentry * dentry = file->f_dentry;
ssize_t result;
- dfprintk(VFS, "nfs: read(%x/%ld, %lu@%lu)\n",
- inode->i_dev, inode->i_ino,
- (unsigned long) count,
- (unsigned long) *ppos);
+ dfprintk(VFS, "nfs: read(%s/%s, %lu@%lu)\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name,
+ (unsigned long) count, (unsigned long) *ppos);
- result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+ result = nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
if (!result)
result = generic_file_read(file, buf, count, ppos);
return result;
static int
nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct dentry *dentry = file->f_dentry;
int status;
- dfprintk(VFS, "nfs: mmap(%x/%ld)\n", inode->i_dev, inode->i_ino);
+ dfprintk(VFS, "nfs: mmap(%s/%s)\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name);
- status = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+ status = nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
if (!status)
status = generic_file_mmap(file, vma);
return status;
static ssize_t
nfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
- struct inode * inode = file->f_dentry->d_inode;
+ struct dentry * dentry = file->f_dentry;
+ struct inode * inode = dentry->d_inode;
ssize_t result;
- dfprintk(VFS, "nfs: write(%x/%ld (%d), %lu@%lu)\n",
- inode->i_dev, inode->i_ino, inode->i_count,
- (unsigned long) count, (unsigned long) *ppos);
+ dfprintk(VFS, "nfs: write(%s/%s (%d), %lu@%lu)\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name,
+ inode->i_count, (unsigned long) count, (unsigned long) *ppos);
if (!inode) {
printk("nfs_file_write: inode = NULL\n");
return -EINVAL;
}
- if (IS_SWAPFILE(inode)) {
- printk("NFS: attempt to write to active swap file!\n");
- return -EBUSY;
- }
- result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+ result = -EBUSY;
+ if (IS_SWAPFILE(inode))
+ goto out_swapfile;
+ result = nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
if (result)
goto out;
- /* N.B. This should be impossible now -- inodes can't change mode */
- if (!S_ISREG(inode->i_mode)) {
- printk("nfs_file_write: write to non-file, mode %07o\n",
- inode->i_mode);
- return -EINVAL;
- }
+#ifdef NFS_PARANOIA
+/* N.B. This should be impossible now -- inodes can't change mode */
+if (!S_ISREG(inode->i_mode)) {
+ printk("nfs_file_write: write to non-file, mode %07o\n",
+ inode->i_mode);
+ return -EINVAL;
+}
+#endif
result = count;
if (!count)
goto out;
result = generic_file_write(file, buf, count, ppos);
out:
return result;
+
+out_swapfile:
+ printk("NFS: attempt to write to active swap file!\n");
+ goto out;
}
/*
static void nfs_read_inode(struct inode *);
static void nfs_put_inode(struct inode *);
static void nfs_delete_inode(struct inode *);
-static int nfs_notify_change(struct inode *, struct iattr *);
+static int nfs_notify_change(struct dentry *, struct iattr *);
static void nfs_put_super(struct super_block *);
static int nfs_statfs(struct super_block *, struct statfs *, int);
nfs_read_super(struct super_block *sb, void *raw_data, int silent)
{
struct nfs_mount_data *data = (struct nfs_mount_data *) raw_data;
- struct sockaddr_in srvaddr;
struct nfs_server *server;
- struct rpc_timeout timeparms;
struct rpc_xprt *xprt;
struct rpc_clnt *clnt;
+ struct nfs_fh *root_fh;
+ struct inode *root_inode;
unsigned int authflavor;
int tcp;
- kdev_t dev = sb->s_dev;
- struct inode *root_inode;
+ struct sockaddr_in srvaddr;
+ struct rpc_timeout timeparms;
MOD_INC_USE_COUNT;
if (!data)
lock_super(sb);
sb->s_magic = NFS_SUPER_MAGIC;
- sb->s_dev = dev;
sb->s_op = &nfs_sops;
sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits);
sb->u.nfs_sb.s_root = data->root;
timeparms.to_maxval = tcp? RPC_MAX_TCP_TIMEOUT : RPC_MAX_UDP_TIMEOUT;
timeparms.to_exponential = 1;
- /* Choose authentication flavor */
- if (data->flags & NFS_MOUNT_SECURE) {
- authflavor = RPC_AUTH_DES;
- } else if (data->flags & NFS_MOUNT_KERBEROS) {
- authflavor = RPC_AUTH_KRB;
- } else {
- authflavor = RPC_AUTH_UNIX;
- }
-
/* Now create transport and client */
xprt = xprt_create_proto(tcp? IPPROTO_TCP : IPPROTO_UDP,
&srvaddr, &timeparms);
if (xprt == NULL)
goto out_no_xprt;
+ /* Choose authentication flavor */
+ authflavor = RPC_AUTH_UNIX;
+ if (data->flags & NFS_MOUNT_SECURE)
+ authflavor = RPC_AUTH_DES;
+ else if (data->flags & NFS_MOUNT_KERBEROS)
+ authflavor = RPC_AUTH_KRB;
+
clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
NFS_VERSION, authflavor);
if (clnt == NULL)
* Keep the super block locked while we try to get
* the root fh attributes.
*/
+ root_fh = kmalloc(sizeof(struct nfs_fh), GFP_KERNEL);
+ if (!root_fh)
+ goto out_no_fh;
+ *root_fh = data->root;
+
root_inode = nfs_fhget(sb, &data->root, NULL);
if (!root_inode)
goto out_no_root;
sb->s_root = d_alloc_root(root_inode, NULL);
if (!sb->s_root)
goto out_no_root;
+ sb->s_root->d_op = &nfs_dentry_operations;
+ sb->s_root->d_fsdata = root_fh;
+
/* We're airborne */
unlock_super(sb);
out_no_root:
printk("nfs_read_super: get root inode failed\n");
iput(root_inode);
+ kfree(root_fh);
+out_no_fh:
rpciod_down();
goto out_shutdown;
nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle,
struct nfs_fattr *fattr)
{
- struct nfs_fattr newfattr;
int error;
- struct inode *inode;
+ struct inode *inode = NULL;
+ struct nfs_fattr newfattr;
- if (!sb) {
- printk("nfs_fhget: super block is NULL\n");
- return NULL;
- }
+ if (!sb)
+ goto out_bad_args;
if (!fattr) {
- error = nfs_proc_getattr(&sb->u.nfs_sb.s_server, fhandle,
- &newfattr);
- if (error) {
- printk("nfs_fhget: getattr error = %d\n", -error);
- return NULL;
- }
fattr = &newfattr;
+ error = nfs_proc_getattr(&sb->u.nfs_sb.s_server, fhandle,fattr);
+ if (error)
+ goto out_bad_attr;
}
- if (!(inode = iget(sb, fattr->fileid))) {
- printk("nfs_fhget: iget failed\n");
- return NULL;
- }
+ inode = iget(sb, fattr->fileid);
+ if (!inode)
+ goto out_no_inode;
#ifdef NFS_PARANOIA
if (inode->i_dev != sb->s_dev)
printk("nfs_fhget: impossible\n");
#endif
- if (inode->i_ino != fattr->fileid) {
- printk("nfs_fhget: unexpected inode from iget\n");
- return inode;
- }
+ if (inode->i_ino != fattr->fileid)
+ goto out_bad_id;
/*
* Check whether the mode has been set, as we only want to
inode->i_size = fattr->size;
inode->i_mtime = fattr->mtime.seconds;
NFS_OLDMTIME(inode) = fattr->mtime.seconds;
- *NFS_FH(inode) = *fhandle;
}
- if (memcmp(NFS_FH(inode), fhandle, sizeof(struct nfs_fh)))
- printk("nfs_fhget: fhandle changed!\n");
nfs_refresh_inode(inode, fattr);
dprintk("NFS: fhget(%x/%ld ct=%d)\n",
inode->i_dev, inode->i_ino,
inode->i_count);
+out:
return inode;
+
+out_bad_args:
+ printk("nfs_fhget: super block is NULL\n");
+ goto out;
+out_bad_attr:
+ printk("nfs_fhget: getattr error = %d\n", -error);
+ goto out;
+out_no_inode:
+ printk("nfs_fhget: iget failed\n");
+ goto out;
+out_bad_id:
+ printk("nfs_fhget: unexpected inode from iget\n");
+ goto out;
}
int
-nfs_notify_change(struct inode *inode, struct iattr *attr)
+nfs_notify_change(struct dentry *dentry, struct iattr *attr)
{
+ struct inode *inode = dentry->d_inode;
+ int error;
struct nfs_sattr sattr;
struct nfs_fattr fattr;
- int error;
/*
* Make sure the inode is up-to-date.
*/
- error = nfs_revalidate(inode);
+ error = nfs_revalidate(dentry);
if (error) {
#ifdef NFS_PARANOIA
printk("nfs_notify_change: revalidate failed, error=%d\n", error);
sattr.atime.useconds = 0;
}
- error = nfs_proc_setattr(NFS_SERVER(inode), NFS_FH(inode),
+ error = nfs_proc_setattr(NFS_DSERVER(dentry), NFS_FH(dentry),
&sattr, &fattr);
if (error)
goto out;
* Externally visible revalidation function
*/
int
-nfs_revalidate(struct inode *inode)
+nfs_revalidate(struct dentry *dentry)
{
- return nfs_revalidate_inode(NFS_SERVER(inode), inode);
+ return nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
}
/*
* the cached attributes have to be refreshed.
*/
int
-_nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
+_nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry)
{
- struct nfs_fattr fattr;
+ struct inode *inode = dentry->d_inode;
int status = 0;
+ struct nfs_fattr fattr;
if (jiffies - NFS_READTIME(inode) < NFS_ATTRTIMEO(inode))
goto out;
- dfprintk(PAGECACHE, "NFS: revalidating %x/%ld inode\n",
- inode->i_dev, inode->i_ino);
- status = nfs_proc_getattr(server, NFS_FH(inode), &fattr);
+ dfprintk(PAGECACHE, "NFS: revalidating %s/%s, ino=%ld\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name,
+ inode->i_ino);
+ status = nfs_proc_getattr(server, NFS_FH(dentry), &fattr);
if (status) {
#ifdef NFS_PARANOIA
-printk("nfs_revalidate_inode: getattr failed, error=%d\n", status);
+printk("nfs_revalidate_inode: %s/%s getattr failed, ino=%ld, error=%d\n",
+dentry->d_parent->d_name.name, dentry->d_name.name, inode->i_ino, status);
#endif
- goto done;
+ goto out;
}
status = nfs_refresh_inode(inode, &fattr);
- if (status)
- goto done;
+ if (status) {
+#ifdef NFS_PARANOIA
+printk("nfs_revalidate_inode: %s/%s refresh failed, ino=%ld, error=%d\n",
+dentry->d_parent->d_name.name, dentry->d_name.name, inode->i_ino, status);
+#endif
+ goto out;
+ }
if (fattr.mtime.seconds == NFS_OLDMTIME(inode)) {
/* Update attrtimeo value */
if ((NFS_ATTRTIMEO(inode) <<= 1) > NFS_MAXATTRTIMEO(inode))
NFS_ATTRTIMEO(inode) = NFS_MAXATTRTIMEO(inode);
}
NFS_OLDMTIME(inode) = fattr.mtime.seconds;
-
-done:
- dfprintk(PAGECACHE,
- "NFS: inode %x/%ld revalidation complete (status %d).\n",
- inode->i_dev, inode->i_ino, status);
+ dfprintk(PAGECACHE, "NFS: %s/%s revalidation complete\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name);
out:
return status;
}
goto out;
}
if (inode->i_ino != fattr->fileid) {
- printk("nfs_refresh_inode: inode number mismatch\n");
+ printk("nfs_refresh_inode: mismatch, ino=%ld, fattr=%d\n",
+ inode->i_ino, fattr->fileid);
goto out;
}
/*
* Read a page synchronously.
*/
-int
-nfs_readpage_sync(struct inode *inode, struct page *page)
+static int
+nfs_readpage_sync(struct dentry *dentry, struct inode *inode, struct page *page)
{
struct nfs_rreq rqst;
unsigned long offset = page->offset;
if (count < rsize)
rsize = count;
- dprintk("NFS: nfs_proc_read(%s, (%x,%lx), %ld, %d, %p)\n",
- NFS_SERVER(inode)->hostname, inode->i_dev,
- inode->i_ino, offset, rsize, buffer);
+ dprintk("NFS: nfs_proc_read(%s, (%s/%s), %ld, %d, %p)\n",
+ NFS_SERVER(inode)->hostname,
+ dentry->d_parent->d_name.name, dentry->d_name.name,
+ offset, rsize, buffer);
/* Set up arguments and perform rpc call */
- nfs_readreq_setup(&rqst, NFS_FH(inode), offset, buffer, rsize);
+ nfs_readreq_setup(&rqst, NFS_FH(dentry), offset, buffer, rsize);
result = rpc_call(NFS_CLIENT(inode), NFSPROC_READ,
&rqst.ra_args, &rqst.ra_res, flags);
}
static inline int
-nfs_readpage_async(struct inode *inode, struct page *page)
+nfs_readpage_async(struct dentry *dentry, struct inode *inode,
+ struct page *page)
{
struct nfs_rreq *req;
int result, flags;
}
/* Initialize request */
- nfs_readreq_setup(req, NFS_FH(inode), page->offset,
+ nfs_readreq_setup(req, NFS_FH(dentry), page->offset,
(void *) page_address(page), PAGE_SIZE);
req->ra_inode = inode;
req->ra_page = page;
* - The server is congested.
*/
int
-nfs_readpage(struct inode *inode, struct page *page)
+nfs_readpage(struct dentry *dentry, struct page *page)
{
+ struct inode *inode = dentry->d_inode;
unsigned long address;
int error = -1;
set_bit(PG_locked, &page->flags);
address = page_address(page);
atomic_inc(&page->count);
- if (!IS_SWAPFILE(inode) && !PageError(page)
- && NFS_SERVER(inode)->rsize >= PAGE_SIZE)
- error = nfs_readpage_async(inode, page);
+ if (!IS_SWAPFILE(inode) && !PageError(page) &&
+ NFS_SERVER(inode)->rsize >= PAGE_SIZE)
+ error = nfs_readpage_async(dentry, inode, page);
if (error < 0) /* couldn't enqueue */
- error = nfs_readpage_sync(inode, page);
+ error = nfs_readpage_sync(dentry, inode, page);
if (error < 0 && IS_SWAPFILE(inode))
printk("Aiee.. nfs swap-in of page failed!\n");
free_page(address);
#include <asm/uaccess.h>
-static int nfs_readlink(struct inode *, char *, int);
-static struct dentry *nfs_follow_link(struct inode *, struct dentry *);
+static int nfs_readlink(struct dentry *, char *, int);
+static struct dentry *nfs_follow_link(struct dentry *, struct dentry *);
/*
* symlinks can't do much...
NULL /* permission */
};
-static int nfs_readlink(struct inode *inode, char *buffer, int buflen)
+static int nfs_readlink(struct dentry *dentry, char *buffer, int buflen)
{
int error;
unsigned int len;
char *res;
void *mem;
- dfprintk(VFS, "nfs: readlink(%x/%ld)\n", inode->i_dev, inode->i_ino);
+ dfprintk(VFS, "nfs: readlink(%s/%s)\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name);
if (buflen > NFS_MAXPATHLEN)
buflen = NFS_MAXPATHLEN;
- error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), &mem,
- &res, &len, buflen);
+ error = nfs_proc_readlink(NFS_DSERVER(dentry), NFS_FH(dentry),
+ &mem, &res, &len, buflen);
if (! error) {
copy_to_user(buffer, res, len);
put_user('\0', buffer + len);
return error;
}
-static struct dentry * nfs_follow_link(struct inode * inode, struct dentry *base)
+static struct dentry *
+nfs_follow_link(struct dentry * dentry, struct dentry *base)
{
int error;
unsigned int len;
char *res;
void *mem;
char *path;
+ struct dentry *result;
- dfprintk(VFS, "nfs: follow_link(%x/%ld)\n", inode->i_dev, inode->i_ino);
+ dfprintk(VFS, "nfs: follow_link(%s/%s)\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name);
- error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), &mem,
- &res, &len, NFS_MAXPATHLEN);
+ error = nfs_proc_readlink(NFS_DSERVER(dentry), NFS_FH(dentry),
+ &mem, &res, &len, NFS_MAXPATHLEN);
+ result = ERR_PTR(error);
+ if (error)
+ goto out_dput;
- if (error) {
- dput(base);
- return ERR_PTR(error);
- }
+ result = ERR_PTR(-ENOMEM);
path = kmalloc(len + 1, GFP_KERNEL);
- if (!path) {
- dput(base);
- kfree(mem);
- return ERR_PTR(-ENOMEM);
- }
+ if (!path)
+ goto out_mem;
memcpy(path, res, len);
path[len] = 0;
kfree(mem);
- base = lookup_dentry(path, base, 1);
+ result = lookup_dentry(path, base, 1);
kfree(path);
- return base;
+out:
+ return result;
+
+out_mem:
+ kfree(mem);
+out_dput:
+ dput(base);
+ goto out;
}
struct nfs_wreq {
struct rpc_listitem wb_list; /* linked list of req's */
struct rpc_task wb_task; /* RPC task */
+ struct dentry * wb_dentry; /* dentry referenced */
struct inode * wb_inode; /* inode referenced */
struct page * wb_page; /* page to be written */
unsigned int wb_offset; /* offset within page */
* Offset is the data offset within the page.
*/
static int
-nfs_writepage_sync(struct inode *inode, struct page *page,
- unsigned long offset, unsigned int count)
+nfs_writepage_sync(struct dentry *dentry, struct inode *inode,
+ struct page *page, unsigned long offset, unsigned int count)
{
- struct nfs_fattr fattr;
unsigned int wsize = NFS_SERVER(inode)->wsize;
int result, refresh = 0, written = 0;
u8 *buffer;
+ struct nfs_fattr fattr;
- dprintk("NFS: nfs_writepage_sync(%x/%ld %d@%ld)\n",
- inode->i_dev, inode->i_ino,
- count, page->offset + offset);
+ dprintk("NFS: nfs_writepage_sync(%s/%s %d@%ld)\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name,
+ count, page->offset + offset);
buffer = (u8 *) page_address(page) + offset;
offset += page->offset;
if (count < wsize && !IS_SWAPFILE(inode))
wsize = count;
- result = nfs_proc_write(NFS_SERVER(inode), NFS_FH(inode),
+ result = nfs_proc_write(NFS_DSERVER(dentry), NFS_FH(dentry),
IS_SWAPFILE(inode), offset, wsize,
buffer, &fattr);
* Create and initialize a writeback request
*/
static inline struct nfs_wreq *
-create_write_request(struct inode *inode, struct page *page,
- unsigned int offset, unsigned int bytes)
+create_write_request(struct dentry *dentry, struct inode *inode,
+ struct page *page, unsigned int offset, unsigned int bytes)
{
struct nfs_wreq *wreq;
struct rpc_clnt *clnt = NFS_CLIENT(inode);
struct rpc_task *task;
- dprintk("NFS: create_write_request(%x/%ld, %ld+%d)\n",
- inode->i_dev, inode->i_ino,
- page->offset + offset, bytes);
+ dprintk("NFS: create_write_request(%s/%s, %ld+%d)\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name,
+ page->offset + offset, bytes);
/* FIXME: Enforce hard limit on number of concurrent writes? */
goto out_req;
/* Put the task on inode's writeback request list. */
+ wreq->wb_dentry = dentry;
wreq->wb_inode = inode;
wreq->wb_pid = current->pid;
wreq->wb_page = page;
* (for now), and we currently do this synchronously only.
*/
int
-nfs_writepage(struct inode *inode, struct page *page)
+nfs_writepage(struct dentry *dentry, struct page *page)
{
- return nfs_writepage_sync(inode, page, 0, PAGE_SIZE);
+ return nfs_writepage_sync(dentry, dentry->d_inode, page, 0, PAGE_SIZE);
}
/*
* things with a page scheduled for an RPC call (e.g. invalidate it).
*/
int
-nfs_updatepage(struct inode *inode, struct page *page, const char *buffer,
+nfs_updatepage(struct dentry *dentry, struct page *page, const char *buffer,
unsigned long offset, unsigned int count, int sync)
{
+ struct inode *inode = dentry->d_inode;
struct nfs_wreq *req;
int status = 0, page_locked = 1;
u8 *page_addr;
- dprintk("NFS: nfs_updatepage(%x/%ld %d@%ld, sync=%d)\n",
- inode->i_dev, inode->i_ino,
- count, page->offset+offset, sync);
+ dprintk("NFS: nfs_updatepage(%s/%s %d@%ld, sync=%d)\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name,
+ count, page->offset+offset, sync);
set_bit(PG_locked, &page->flags);
page_addr = (u8 *) page_address(page);
*/
if (NFS_SERVER(inode)->wsize < PAGE_SIZE) {
copy_from_user(page_addr + offset, buffer, count);
- return nfs_writepage_sync(inode, page, offset, count);
+ return nfs_writepage_sync(dentry, inode, page, offset, count);
}
/*
/* Create the write request. */
status = -ENOBUFS;
- req = create_write_request(inode, page, offset, count);
+ req = create_write_request(dentry, inode, page, offset, count);
if (!req)
goto done;
{
struct nfs_wreq *req = (struct nfs_wreq *) task->tk_calldata;
struct page *page = req->wb_page;
- struct inode *inode = req->wb_inode;
+ struct dentry *dentry = req->wb_dentry;
dprintk("NFS: %4d nfs_wback_lock (status %d flags %x)\n",
task->tk_pid, task->tk_status, req->wb_flags);
}
/* Setup the task struct for a writeback call */
- req->wb_args->fh = NFS_FH(inode);
+ req->wb_args->fh = NFS_FH(dentry);
req->wb_args->offset = page->offset + req->wb_offset;
req->wb_args->count = req->wb_bytes;
req->wb_args->buffer = (void *) (page_address(page) + req->wb_offset);
nfs_wback_result(struct rpc_task *task)
{
struct nfs_wreq *req = (struct nfs_wreq *) task->tk_calldata;
- struct inode *inode;
- struct page *page;
- int status;
+ struct inode *inode = req->wb_inode;
+ struct page *page = req->wb_page;
+ int status = task->tk_status;
dprintk("NFS: %4d nfs_wback_result (status %d)\n",
- task->tk_pid, task->tk_status);
-
- inode = req->wb_inode;
- page = req->wb_page;
- status = task->tk_status;
+ task->tk_pid, status);
if (status < 0) {
/*
if (iap->ia_valid) {
iap->ia_valid |= ATTR_CTIME;
iap->ia_ctime = CURRENT_TIME;
- err = notify_change(inode, iap);
+ err = notify_change(dentry, iap);
if (err)
return nfserrno(-err);
if (EX_ISSYNC(fhp->fh_export))
ia.ia_valid = ATTR_MODE;
ia.ia_mode = inode->i_mode & ~(S_ISUID | S_ISGID);
- notify_change(inode, &ia);
+ notify_change(dentry, &ia);
}
fh_unlock(fhp); /* unlock inode */
fh_lock(fhp);
newattrs.ia_size = size;
newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
- err = notify_change(inode, &newattrs);
+ err = notify_change(dentry, &newattrs);
if (!err) {
vmtruncate(inode, size);
if (inode->i_op && inode->i_op->truncate)
UPDATE_ATIME(inode);
/* N.B. Why does this call need a get_fs()?? */
oldfs = get_fs(); set_fs(KERNEL_DS);
- err = inode->i_op->readlink(inode, buf, *lenp);
+ err = inode->i_op->readlink(dentry, buf, *lenp);
set_fs(oldfs);
if (err < 0)
nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
char *fname, int len, struct svc_fh *tfhp)
{
- struct dentry *ddir, *dnew;
+ struct dentry *ddir, *dnew, *dold;
struct inode *dirp, *dest;
int err;
err = -EEXIST;
if (dnew->d_inode)
goto dput_and_out;
- dest = tfhp->fh_dentry->d_inode;
err = -EPERM;
if (!len)
goto dput_and_out;
+ dold = tfhp->fh_dentry;
+ dest = dold->d_inode;
+
err = -EACCES;
if (nfsd_iscovered(ddir, ffhp->fh_export))
goto dput_and_out;
goto dput_and_out;
fh_lock(ffhp);
- err = dirp->i_op->link(dest, dirp, dnew);
+ err = dirp->i_op->link(dold, dirp, dnew);
fh_unlock(ffhp);
if (!err && EX_ISSYNC(ffhp->fh_export)) {
return error;
}
-int do_truncate(struct inode *inode, unsigned long length)
+int do_truncate(struct dentry *dentry, unsigned long length)
{
+ struct inode *inode = dentry->d_inode;
int error;
struct iattr newattrs;
down(&inode->i_sem);
newattrs.ia_size = length;
newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
- error = notify_change(inode, &newattrs);
+ error = notify_change(dentry, &newattrs);
if (!error) {
/* truncate virtual mappings of this file */
vmtruncate(inode, length);
if (!error) {
if (inode->i_sb && inode->i_sb->dq_op)
inode->i_sb->dq_op->initialize(inode, -1);
- error = do_truncate(inode, length);
+ error = do_truncate(dentry, length);
}
put_write_access(inode);
dput_and_out:
length<inode->i_size ? length : inode->i_size,
abs(inode->i_size - length));
if (!error)
- error = do_truncate(inode, length);
+ error = do_truncate(dentry, length);
}
unlock_kernel();
return error;
(error = permission(inode,MAY_WRITE)) != 0)
goto dput_and_out;
}
- error = notify_change(inode, &newattrs);
+ error = notify_change(dentry, &newattrs);
dput_and_out:
dput(dentry);
out:
if ((error = permission(inode,MAY_WRITE)) != 0)
goto dput_and_out;
}
- error = notify_change(inode, &newattrs);
+ error = notify_change(dentry, &newattrs);
dput_and_out:
dput(dentry);
out:
mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
- err = notify_change(inode, &newattrs);
+ err = notify_change(dentry, &newattrs);
out:
unlock_kernel();
return err;
mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
- error = notify_change(inode, &newattrs);
+ error = notify_change(dentry, &newattrs);
dput_and_out:
dput(dentry);
error = -EDQUOT;
if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0))
goto out;
- error = notify_change(inode, &newattrs);
+ error = notify_change(dentry, &newattrs);
if (error)
inode->i_sb->dq_op->transfer(inode, &newattrs, 1);
} else
- error = notify_change(inode, &newattrs);
+ error = notify_change(dentry, &newattrs);
out:
return error;
}
#include <linux/proc_fs.h>
#include <linux/stat.h>
-static int proc_readlink(struct inode *, char *, int);
-static struct dentry * proc_follow_link(struct inode *, struct dentry *);
+static int proc_readlink(struct dentry *, char *, int);
+static struct dentry * proc_follow_link(struct dentry *, struct dentry *);
/*
* PLAN9_SEMANTICS won't work any more: it used an ugly hack that broke
NULL /* permission */
};
-static struct dentry * proc_follow_link(struct inode *inode, struct dentry *base)
+static struct dentry * proc_follow_link(struct dentry *dentry,
+ struct dentry *base)
{
+ struct inode *inode = dentry->d_inode;
struct task_struct *p;
struct dentry * result;
int ino, pid;
error = permission(inode, MAY_EXEC);
result = ERR_PTR(error);
if (error)
- return result;
+ goto out;
ino = inode->i_ino;
pid = ino >> 16;
p = find_task_by_pid(pid);
result = ERR_PTR(-ENOENT);
if (!p)
- return result;
+ goto out;
switch (ino) {
case PROC_PID_CWD:
break;
}
}
+out:
return result;
}
-static int proc_readlink(struct inode * inode, char * buffer, int buflen)
+static int proc_readlink(struct dentry * dentry, char * buffer, int buflen)
{
int error;
- struct dentry * dentry = proc_follow_link(inode, NULL);
+ dentry = proc_follow_link(dentry, NULL);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
error = -ENOENT;
NULL /* smap */
};
-static struct dentry *devtree_follow_link(struct inode *inode,
+static struct dentry *devtree_follow_link(struct dentry *dentry,
struct dentry *base)
{
struct proc_dir_entry * de;
char *link;
- de = (struct proc_dir_entry *) inode->u.generic_ip;
+ de = (struct proc_dir_entry *) dentry->inode->u.generic_ip;
link = (char *) de->data;
return lookup_dentry(link, base, 1);
}
-static int devtree_readlink(struct inode *inode, char *buffer, int buflen)
+static int devtree_readlink(struct dentry *dentry, char *buffer, int buflen)
{
struct proc_dir_entry * de;
char *link;
int linklen;
- de = (struct proc_dir_entry *) inode->u.generic_ip;
+ de = (struct proc_dir_entry *) dentry->inode->u.generic_ip;
link = (char *) de->data;
linklen = strlen(link);
if (linklen > buflen)
/*
* /proc/self:
*/
-static int proc_self_readlink(struct inode * inode, char * buffer, int buflen)
+static int proc_self_readlink(struct dentry *dentry, char *buffer, int buflen)
{
int len;
char tmp[30];
return len;
}
-static struct dentry * proc_self_follow_link(struct inode *inode, struct dentry *base)
+static struct dentry * proc_self_follow_link(struct dentry *dentry,
+ struct dentry *base)
{
- int len;
char tmp[30];
- len = sprintf(tmp, "%d", current->pid);
+ sprintf(tmp, "%d", current->pid);
return lookup_dentry(tmp, base, 1);
}
*/
static int
-romfs_readpage(struct inode * inode, struct page * page)
+romfs_readpage(struct dentry * dentry, struct page * page)
{
+ struct inode *inode = dentry->d_inode;
unsigned long buf;
unsigned long offset, avail, readlen;
int result = -EIO;
}
static int
-romfs_readlink(struct inode *inode, char *buffer, int len)
+romfs_readlink(struct dentry *dentry, char *buffer, int len)
{
+ struct inode *inode = dentry->d_inode;
int mylen;
char buf[ROMFS_MAXFN]; /* XXX dynamic */
return mylen;
}
-static struct dentry *romfs_follow_link(struct inode *inode, struct dentry *base)
+static struct dentry *romfs_follow_link(struct dentry *dentry,
+ struct dentry *base)
{
+ struct inode *inode = dentry->d_inode;
char *link;
int len, cnt;
- struct dentry *dentry;
len = inode->i_size;
/*
* Make sure our inode is up-to-date.
*/
- result = smb_revalidate_inode(dir);
+ result = smb_revalidate_inode(dentry);
if (result)
goto out;
/*
}
if (server->conn_pid)
- error = smb_revalidate_inode(dir);
+ error = smb_revalidate_inode(dentry);
return error;
}
#endif
valid = 0;
} else if (!valid)
- valid = (smb_revalidate_inode(inode) == 0);
+ valid = (smb_revalidate_inode(dentry) == 0);
} else
{
/*
* Read a page synchronously.
*/
static int
-smb_readpage_sync(struct inode *inode, struct page *page)
+smb_readpage_sync(struct dentry *dentry, struct page *page)
{
+ struct inode *inode = dentry->d_inode;
char *buffer = (char *) page_address(page);
unsigned long offset = page->offset;
- struct dentry * dentry = inode->u.smbfs_i.dentry;
int rsize = smb_get_rsize(SMB_SERVER(inode));
int count = PAGE_SIZE;
int result;
clear_bit(PG_error, &page->flags);
- result = -EIO;
- if (!dentry) {
- printk("smb_readpage_sync: no dentry for inode %ld\n",
- inode->i_ino);
- goto io_error;
- }
-
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_readpage_sync: file %s/%s, count=%d@%ld, rsize=%d\n",
dentry->d_parent->d_name.name, dentry->d_name.name, count, offset, rsize);
}
int
-smb_readpage(struct inode *inode, struct page *page)
+smb_readpage(struct dentry *dentry, struct page *page)
{
int error;
#endif
set_bit(PG_locked, &page->flags);
atomic_inc(&page->count);
- error = smb_readpage_sync(inode, page);
+ error = smb_readpage_sync(dentry, page);
free_page(page_address(page));
return error;
}
* Offset is the data offset within the page.
*/
static int
-smb_writepage_sync(struct inode *inode, struct page *page,
+smb_writepage_sync(struct dentry *dentry, struct page *page,
unsigned long offset, unsigned int count)
{
+ struct inode *inode = dentry->d_inode;
u8 *buffer = (u8 *) page_address(page) + offset;
int wsize = smb_get_wsize(SMB_SERVER(inode));
int result, written = 0;
offset += page->offset;
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_writepage_sync: file %s/%s, count=%d@%ld, wsize=%d\n",
-((struct dentry *) inode->u.smbfs_i.dentry)->d_parent->d_name.name,
-((struct dentry *) inode->u.smbfs_i.dentry)->d_name.name, count, offset, wsize);
+dentry->d_parent->d_name.name, dentry->d_name.name, count, offset, wsize);
#endif
do {
* (for now), and we currently do this synchronously only.
*/
static int
-smb_writepage(struct inode *inode, struct page *page)
+smb_writepage(struct dentry *dentry, struct page *page)
{
int result;
#endif
set_bit(PG_locked, &page->flags);
atomic_inc(&page->count);
- result = smb_writepage_sync(inode, page, 0, PAGE_SIZE);
+ result = smb_writepage_sync(dentry, page, 0, PAGE_SIZE);
free_page(page_address(page));
return result;
}
static int
-smb_updatepage(struct inode *inode, struct page *page, const char *buffer,
+smb_updatepage(struct dentry *dentry, struct page *page, const char *buffer,
unsigned long offset, unsigned int count, int sync)
{
unsigned long page_addr = page_address(page);
int result;
- pr_debug("SMB: smb_updatepage(%x/%ld %d@%ld, sync=%d)\n",
- inode->i_dev, inode->i_ino,
- count, page->offset+offset, sync);
+ pr_debug("SMBFS: smb_updatepage(%s/%s %d@%ld, sync=%d)\n",
+ dentry->d_parent->d_name.name, dentry->d_name.name,
+ count, page->offset+offset, sync);
#ifdef SMBFS_PARANOIA
if (test_bit(PG_locked, &page->flags))
if (copy_from_user((char *) page_addr + offset, buffer, count))
goto bad_fault;
- result = smb_writepage_sync(inode, page, offset, count);
+ result = smb_writepage_sync(dentry, page, offset, count);
out:
free_page(page_addr);
return result;
smb_file_read(struct file * file, char * buf, size_t count, loff_t *ppos)
{
struct dentry * dentry = file->f_dentry;
- struct inode * inode = dentry->d_inode;
ssize_t status;
#ifdef SMBFS_DEBUG_VERBOSE
(unsigned long) count, (unsigned long) *ppos);
#endif
- status = smb_revalidate_inode(inode);
+ status = smb_revalidate_inode(dentry);
if (status)
{
#ifdef SMBFS_PARANOIA
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_file_read: before read, size=%ld, pages=%ld, flags=%x, atime=%ld\n",
-inode->i_size, inode->i_nrpages, inode->i_flags, inode->i_atime);
+dentry->d_inode->i_size, dentry->d_inode->i_nrpages, dentry->d_inode->i_flags,
+dentry->d_inode->i_atime);
#endif
status = generic_file_read(file, buf, count, ppos);
out:
smb_file_mmap(struct file * file, struct vm_area_struct * vma)
{
struct dentry * dentry = file->f_dentry;
- struct inode * inode = dentry->d_inode;
int status;
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_file_mmap: file %s/%s, address %lu - %lu\n",
-dentry->d_parent->d_name.name, dentry->d_name.name,
-vma->vm_start, vma->vm_end);
+dentry->d_parent->d_name.name, dentry->d_name.name, vma->vm_start, vma->vm_end);
#endif
- status = smb_revalidate_inode(inode);
+ status = smb_revalidate_inode(dentry);
if (status)
{
#ifdef SMBFS_PARANOIA
smb_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
struct dentry * dentry = file->f_dentry;
- struct inode * inode = dentry->d_inode;
ssize_t result;
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_file_write: file %s/%s, count=%lu@%lu, pages=%ld\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
-(unsigned long) count, (unsigned long) *ppos, inode->i_nrpages);
+(unsigned long) count, (unsigned long) *ppos, dentry->d_inode->i_nrpages);
#endif
- result = smb_revalidate_inode(inode);
+ result = smb_revalidate_inode(dentry);
if (result)
{
#ifdef SMBFS_PARANOIA
result = generic_file_write(file, buf, count, ppos);
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_file_write: pos=%ld, size=%ld, mtime=%ld, atime=%ld\n",
-(long) file->f_pos, inode->i_size, inode->i_mtime, inode->i_atime);
+(long) file->f_pos, dentry->d_inode->i_size, dentry->d_inode->i_mtime,
+dentry->d_inode->i_atime);
#endif
}
out:
* invalidate our local caches.
*/
int
-smb_revalidate_inode(struct inode *inode)
+smb_revalidate_inode(struct dentry *dentry)
{
+ struct inode *inode = dentry->d_inode;
time_t last_time;
int error = 0;
{
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_revalidate: %s/%s changed, old=%ld, new=%ld\n",
-((struct dentry *)inode->u.smbfs_i.dentry)->d_parent->d_name.name,
-((struct dentry *)inode->u.smbfs_i.dentry)->d_name.name,
+dentry->d_parent->d_name.name, dentry->d_name.name,
(long) last_time, (long) inode->i_mtime);
#endif
if (!S_ISDIR(inode->i_mode))
}
int
-smb_notify_change(struct inode *inode, struct iattr *attr)
+smb_notify_change(struct dentry *dentry, struct iattr *attr)
{
- struct smb_sb_info *server = SMB_SERVER(inode);
- struct dentry *dentry = inode->u.smbfs_i.dentry;
+ struct inode *inode = dentry->d_inode;
+ struct smb_sb_info *server = server_from_dentry(dentry);
unsigned int mask = (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO);
int error, changed, refresh = 0;
struct smb_fattr fattr;
- error = -EIO;
- if (!dentry)
- {
- printk("smb_notify_change: no dentry for inode!\n");
- goto out;
- }
-
- error = smb_revalidate_inode(inode);
+ error = smb_revalidate_inode(dentry);
if (error)
goto out;
* Revalidate the inode. This is required for proper NFS attribute caching.
*/
static __inline__ int
-do_revalidate(struct inode *inode)
+do_revalidate(struct dentry *dentry)
{
+ struct inode * inode = dentry->d_inode;
if (inode->i_op && inode->i_op->revalidate)
- return inode->i_op->revalidate(inode);
+ return inode->i_op->revalidate(dentry);
return 0;
}
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
- struct inode * inode = dentry->d_inode;
- error = do_revalidate(inode);
+ error = do_revalidate(dentry);
if (!error)
- error = cp_old_stat(inode, statbuf);
+ error = cp_old_stat(dentry->d_inode, statbuf);
dput(dentry);
}
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
- struct inode * inode = dentry->d_inode;
- error = do_revalidate(inode);
+ error = do_revalidate(dentry);
if (!error)
- error = cp_new_stat(inode,statbuf);
+ error = cp_new_stat(dentry->d_inode, statbuf);
dput(dentry);
}
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
- struct inode * inode = dentry->d_inode;
- error = do_revalidate(inode);
+ error = do_revalidate(dentry);
if (!error)
- error = cp_old_stat(inode, statbuf);
+ error = cp_old_stat(dentry->d_inode, statbuf);
dput(dentry);
}
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
- struct inode * inode = dentry->d_inode;
- error = do_revalidate(inode);
+ error = do_revalidate(dentry);
if (!error)
- error = cp_new_stat(inode,statbuf);
+ error = cp_new_stat(dentry->d_inode, statbuf);
dput(dentry);
}
lock_kernel();
if (fd < NR_OPEN && (f = current->files->fd[fd]) != NULL) {
struct dentry * dentry = f->f_dentry;
- struct inode * inode = dentry->d_inode;
- err = do_revalidate(inode);
+ err = do_revalidate(dentry);
if (!err)
- err = cp_old_stat(inode,statbuf);
+ err = cp_old_stat(dentry->d_inode, statbuf);
}
unlock_kernel();
return err;
lock_kernel();
if (fd < NR_OPEN && (f = current->files->fd[fd]) != NULL) {
struct dentry * dentry = f->f_dentry;
- struct inode * inode = dentry->d_inode;
- err = do_revalidate(inode);
+ err = do_revalidate(dentry);
if (!err)
- err = cp_new_stat(inode,statbuf);
+ err = cp_new_stat(dentry->d_inode, statbuf);
}
unlock_kernel();
return err;
struct inode * inode = dentry->d_inode;
error = -EINVAL;
- if (inode->i_op && inode->i_op->readlink && !(error = do_revalidate(inode))) {
+ if (inode->i_op && inode->i_op->readlink &&
+ !(error = do_revalidate(dentry))) {
UPDATE_ATIME(inode);
- error = inode->i_op->readlink(inode,buf,bufsiz);
+ error = inode->i_op->readlink(dentry, buf, bufsiz);
}
dput(dentry);
}
}
/* To avoid inconsistencies between inodes in memory and inodes on disk. */
-extern int sysv_notify_change(struct inode *inode, struct iattr *attr)
+extern int sysv_notify_change(struct dentry *dentry, struct iattr *attr)
{
+ struct inode *inode = dentry->d_inode;
int error;
if ((error = inode_change_ok(inode, attr)) != 0)
#include <asm/uaccess.h>
-static int sysv_readlink(struct inode *, char *, int);
-static struct dentry *sysv_follow_link(struct inode *, struct dentry *);
+static int sysv_readlink(struct dentry *, char *, int);
+static struct dentry *sysv_follow_link(struct dentry *, struct dentry *);
/*
* symlinks can't do much...
NULL /* permission */
};
-static struct dentry *sysv_follow_link(struct inode * inode, struct dentry * base)
+static struct dentry *sysv_follow_link(struct dentry * dentry,
+ struct dentry * base)
{
+ struct inode *inode = dentry->d_inode;
struct buffer_head * bh;
bh = sysv_file_bread(inode, 0, 0);
return base;
}
-static int sysv_readlink(struct inode * inode, char * buffer, int buflen)
+static int sysv_readlink(struct dentry * dentry, char * buffer, int buflen)
{
+ struct inode *inode = dentry->d_inode;
struct buffer_head * bh;
char * bh_data;
int i;
extern int ufs_bmap (struct inode *, int);
static int
-ufs_readlink(struct inode * inode, char * buffer, int buflen)
+ufs_readlink(struct dentry * dentry, char * buffer, int buflen)
{
+ struct inode * inode = dentry->d_inode;
unsigned long int block;
struct buffer_head * bh = NULL;
char * link;
* XXX - blatantly stolen from minix fs
*/
static struct dentry *
-ufs_follow_link(struct inode * inode, struct dentry * base)
+ufs_follow_link(struct dentry * dentry, struct dentry * base)
{
+ struct inode * inode = dentry->d_inode;
unsigned long int block;
struct buffer_head * bh = NULL;
char * link;
struct dentry_operations *d_op;
struct super_block * d_sb; /* The root of the dentry tree */
unsigned long d_reftime; /* last time referenced */
+ void * d_fsdata; /* fs-specific data */
};
struct dentry_operations {
int (*d_hash) (struct dentry *,struct qstr *);
int (*d_compare) (struct dentry *,struct qstr *, struct qstr *);
void (*d_delete)(struct dentry *);
+ void (*d_release)(struct dentry *);
};
/* the dentry parameter passed to d_hash and d_compare is the parent
extern int ext2_rmdir (struct inode *,struct dentry *);
extern int ext2_unlink (struct inode *,struct dentry *);
extern int ext2_symlink (struct inode *,struct dentry *,const char *);
-extern int ext2_link (struct inode *, struct inode *, struct dentry *);
+extern int ext2_link (struct dentry *, struct inode *, struct dentry *);
extern int ext2_mknod (struct inode *, struct dentry *, int, int);
-extern int ext2_rename (struct inode *, struct dentry *,struct inode *, struct dentry *);
+extern int ext2_rename (struct inode *, struct dentry *,
+ struct inode *, struct dentry *);
/* super.c */
extern void ext2_error (struct super_block *, const char *, const char *, ...)
struct file_operations * default_file_ops;
int (*create) (struct inode *,struct dentry *,int);
int (*lookup) (struct inode *,struct dentry *);
- int (*link) (struct inode *,struct inode *,struct dentry *);
+ int (*link) (struct dentry *,struct inode *,struct dentry *);
int (*unlink) (struct inode *,struct dentry *);
int (*symlink) (struct inode *,struct dentry *,const char *);
int (*mkdir) (struct inode *,struct dentry *,int);
int (*rmdir) (struct inode *,struct dentry *);
int (*mknod) (struct inode *,struct dentry *,int,int);
- int (*rename) (struct inode *,struct dentry *,struct inode *,struct dentry *);
- int (*readlink) (struct inode *,char *,int);
- struct dentry * (*follow_link) (struct inode *, struct dentry *);
- int (*readpage) (struct inode *, struct page *);
- int (*writepage) (struct inode *, struct page *);
+ int (*rename) (struct inode *, struct dentry *,
+ struct inode *, struct dentry *);
+ int (*readlink) (struct dentry *, char *,int);
+ struct dentry * (*follow_link) (struct dentry *, struct dentry *);
+ int (*readpage) (struct dentry *, struct page *);
+ int (*writepage) (struct dentry *, struct page *);
int (*bmap) (struct inode *,int);
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int);
int (*smap) (struct inode *,int);
- int (*updatepage) (struct inode *, struct page *, const char *,
+ int (*updatepage) (struct dentry *, struct page *, const char *,
unsigned long, unsigned int, int);
- int (*revalidate) (struct inode *);
+ int (*revalidate) (struct dentry *);
};
struct super_operations {
void (*write_inode) (struct inode *);
void (*put_inode) (struct inode *);
void (*delete_inode) (struct inode *);
- int (*notify_change) (struct inode *, struct iattr *);
+ int (*notify_change) (struct dentry *, struct iattr *);
void (*put_super) (struct super_block *);
void (*write_super) (struct super_block *);
int (*statfs) (struct super_block *, struct statfs *, int);
extern char * getname(const char * filename);
extern void putname(char * name);
-extern int do_truncate(struct inode *, unsigned long);
+extern int do_truncate(struct dentry *, unsigned long);
extern int register_blkdev(unsigned int, const char *, struct file_operations *);
extern int unregister_blkdev(unsigned int major, const char * name);
extern int blkdev_open(struct inode * inode, struct file * filp);
extern int fsync_dev(kdev_t dev);
extern void sync_supers(kdev_t dev);
extern int bmap(struct inode * inode,int block);
-extern int notify_change(struct inode *, struct iattr *);
+extern int notify_change(struct dentry *, struct iattr *);
extern int permission(struct inode * inode,int mask);
extern int get_write_access(struct inode *inode);
extern void put_write_access(struct inode *inode);
extern int brw_page(int, struct page *, kdev_t, int [], int, int);
-extern int generic_readpage(struct inode *, struct page *);
+extern int generic_readpage(struct dentry *, struct page *);
extern int generic_file_mmap(struct file *, struct vm_area_struct *);
extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *);
extern ssize_t generic_file_write(struct file *, const char*, size_t, loff_t*);
extern int inode_change_ok(struct inode *, struct iattr *);
extern void inode_setattr(struct inode *, struct iattr *);
-extern int notify_change(struct inode * inode, struct iattr * attr);
/* kludge to get SCSI modules working */
#include <linux/minix_fs.h>
/* inode.c */
extern int fat_bmap(struct inode *inode,int block);
-extern int fat_notify_change(struct inode *,struct iattr *);
+extern int fat_notify_change(struct dentry *, struct iattr *);
extern void fat_put_inode(struct inode *inode);
extern void fat_delete_inode(struct inode *inode);
extern void fat_put_super(struct super_block *sb);
#include <linux/signal.h>
#include <linux/sched.h>
-#include <linux/nfs.h>
#include <linux/in.h>
+
#include <linux/sunrpc/debug.h>
+#include <linux/nfs.h>
#include <linux/nfs_mount.h>
/*
*/
#define NFS_SUPER_MAGIC 0x6969
+#define NFS_FH(dentry) ((struct nfs_fh *) ((dentry)->d_fsdata))
+#define NFS_DSERVER(dentry) (&(dentry)->d_sb->u.nfs_sb.s_server)
#define NFS_SERVER(inode) (&(inode)->i_sb->u.nfs_sb.s_server)
#define NFS_CLIENT(inode) (NFS_SERVER(inode)->client)
#define NFS_ADDR(inode) (RPC_PEERADDR(NFS_CLIENT(inode)))
#define NFS_CONGESTED(inode) (RPC_CONGESTED(NFS_CLIENT(inode)))
-#define NFS_FH(inode) (&(inode)->u.nfs_i.fhandle)
#define NFS_READTIME(inode) ((inode)->u.nfs_i.read_cache_jiffies)
#define NFS_OLDMTIME(inode) ((inode)->u.nfs_i.read_cache_mtime)
extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *,
struct nfs_fattr *);
extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
-extern int nfs_revalidate(struct inode *);
-extern int _nfs_revalidate_inode(struct nfs_server *, struct inode *);
+extern int nfs_revalidate(struct dentry *);
+extern int _nfs_revalidate_inode(struct nfs_server *, struct dentry *);
/*
* linux/fs/nfs/file.c
* linux/fs/nfs/dir.c
*/
extern struct inode_operations nfs_dir_inode_operations;
+extern struct dentry_operations nfs_dentry_operations;
extern void nfs_free_dircache(void);
extern void nfs_invalidate_dircache(struct inode *);
extern void nfs_invalidate_dircache_sb(struct super_block *);
/*
* linux/fs/nfs/locks.c
*/
-extern int nfs_lock(struct file *file, int cmd, struct file_lock *fl);
+extern int nfs_lock(struct file *, int, struct file_lock *);
/*
* linux/fs/nfs/write.c
*/
-extern int nfs_writepage(struct inode *, struct page *);
+extern int nfs_writepage(struct dentry *, struct page *);
extern int nfs_check_failed_request(struct inode *);
extern int nfs_check_error(struct inode *);
extern int nfs_flush_dirty_pages(struct inode *, pid_t, off_t, off_t);
extern int nfs_truncate_dirty_pages(struct inode *, unsigned long);
extern void nfs_invalidate_pages(struct inode *);
-extern int nfs_updatepage(struct inode *, struct page *, const char *,
+extern int nfs_updatepage(struct dentry *, struct page *, const char *,
unsigned long, unsigned int, int);
/*
* linux/fs/nfs/read.c
*/
-extern int nfs_readpage(struct inode *, struct page *);
-extern int nfs_readpage_sync(struct inode *, struct page *);
+extern int nfs_readpage(struct dentry *, struct page *);
/*
* linux/fs/mount_clnt.c
* inline functions
*/
static inline int
-nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
+nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry)
{
+ struct inode *inode = dentry->d_inode;
if (jiffies - NFS_READTIME(inode) < NFS_ATTRTIMEO(inode))
return 0;
- return _nfs_revalidate_inode(server, inode);
+ return _nfs_revalidate_inode(server, dentry);
}
extern struct nfs_wreq * nfs_failed_requests;
*/
struct pipe_inode_info pipeinfo;
- /*
- * The file handle
- */
- struct nfs_fh fhandle;
-
/*
* Various flags
*/
struct super_block *smb_read_super(struct super_block *, void *, int);
void smb_get_inode_attr(struct inode *, struct smb_fattr *);
void smb_invalidate_inodes(struct smb_sb_info *);
-int smb_revalidate_inode(struct inode *);
+int smb_revalidate_inode(struct dentry *);
int smb_refresh_inode(struct inode *);
-int smb_notify_change(struct inode *, struct iattr *);
+int smb_notify_change(struct dentry *, struct iattr *);
unsigned long smb_invent_inos(unsigned long);
struct inode *smb_iget(struct super_block *, struct smb_fattr *);
* that we could use for the cache (if it is 0 we can try to create one,
* this is all overlapped with the IO on the previous page finishing anyway)
*/
-static unsigned long try_to_read_ahead(struct inode * inode, unsigned long offset, unsigned long page_cache)
+static unsigned long try_to_read_ahead(struct dentry * dentry,
+ unsigned long offset, unsigned long page_cache)
{
+ struct inode *inode = dentry->d_inode;
struct page * page;
struct page ** hash;
*/
page = mem_map + MAP_NR(page_cache);
add_to_page_cache(page, inode, offset, hash);
- inode->i_op->readpage(inode, page);
+ inode->i_op->readpage(dentry, page);
page_cache = 0;
}
release_page(page);
return max_readahead[MAJOR(inode->i_dev)][MINOR(inode->i_dev)];
}
-static inline unsigned long generic_file_readahead(int reada_ok, struct file * filp, struct inode * inode,
- unsigned long ppos, struct page * page,
- unsigned long page_cache)
+static inline unsigned long generic_file_readahead(int reada_ok,
+ struct file * filp, struct inode * inode,
+ unsigned long ppos, struct page * page, unsigned long page_cache)
{
unsigned long max_ahead, ahead;
unsigned long raend;
ahead = 0;
while (ahead < max_ahead) {
ahead += PAGE_SIZE;
- page_cache = try_to_read_ahead(inode, raend + ahead, page_cache);
+ page_cache = try_to_read_ahead(filp->f_dentry, raend + ahead,
+ page_cache);
}
/*
* If we tried to read ahead some pages,
ssize_t generic_file_read(struct file * filp, char * buf,
size_t count, loff_t *ppos)
{
- struct inode *inode = filp->f_dentry->d_inode;
+ struct dentry *dentry = filp->f_dentry;
+ struct inode *inode = dentry->d_inode;
ssize_t error, read;
size_t pos, pgpos, page_cache;
int reada_ok;
if (reada_ok && filp->f_ramax > MIN_READAHEAD)
filp->f_ramax = MIN_READAHEAD;
- error = inode->i_op->readpage(inode, page);
+ error = inode->i_op->readpage(dentry, page);
if (!error)
goto found_page;
release_page(page);
* Try to re-read it _once_. We do this synchronously,
* because this happens only if there were errors.
*/
- error = inode->i_op->readpage(inode, page);
+ error = inode->i_op->readpage(dentry, page);
if (!error) {
wait_on_page(page);
if (PageUptodate(page) && !PageError(page))
*/
static unsigned long filemap_nopage(struct vm_area_struct * area, unsigned long address, int no_share)
{
+ struct dentry * dentry = area->vm_dentry;
+ struct inode * inode = dentry->d_inode;
unsigned long offset;
struct page * page, **hash;
- struct inode * inode = area->vm_dentry->d_inode;
unsigned long old_page, new_page;
new_page = 0;
new_page = 0;
add_to_page_cache(page, inode, offset, hash);
- if (inode->i_op->readpage(inode, page) != 0)
+ if (inode->i_op->readpage(dentry, page) != 0)
goto failure;
/*
* Do a very limited read-ahead if appropriate
*/
if (PageLocked(page))
- new_page = try_to_read_ahead(inode, offset + PAGE_SIZE, 0);
+ new_page = try_to_read_ahead(dentry, offset + PAGE_SIZE, 0);
goto found_page;
page_locked_wait:
* because there really aren't any performance issues here
* and we need to check for errors.
*/
- if (inode->i_op->readpage(inode, page) != 0)
+ if (inode->i_op->readpage(dentry, page) != 0)
goto failure;
wait_on_page(page);
if (PageError(page))
generic_file_write(struct file *file, const char *buf,
size_t count, loff_t *ppos)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct dentry *dentry = file->f_dentry;
+ struct inode *inode = dentry->d_inode;
struct page *page, **hash;
unsigned long page_cache = 0;
unsigned long pgpos, offset;
*/
if (!PageUptodate(page)) {
if (bytes < PAGE_SIZE && pgpos < inode->i_size) {
+ status = -EIO; /* two tries ... error out */
if (didread < 2)
- status = inode->i_op->readpage(inode, page);
- else
- status = -EIO; /* two tries ... error out */
+ status = inode->i_op->readpage(dentry,
+ page);
if (status < 0)
goto done_with_page;
didread++;
}
/* Alright, the page is there. Now update it. */
- status = inode->i_op->updatepage(inode, page, buf,
+ status = inode->i_op->updatepage(dentry, page, buf,
offset, bytes, sync);
done_with_page:
__free_page(page);