Commit 61d292a7 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://gkernel.bkbits.net/net-drivers-2.5

into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
parents 773ee447 077f48d1
......@@ -32,10 +32,9 @@
typedef struct svc_client svc_client;
typedef struct svc_export svc_export;
static svc_export * exp_find(svc_client *clp, kdev_t dev);
static svc_export * exp_parent(svc_client *clp, kdev_t dev,
static svc_export * exp_parent(svc_client *clp, struct super_block *sb,
struct dentry *dentry);
static svc_export * exp_child(svc_client *clp, kdev_t dev,
static svc_export * exp_child(svc_client *clp, struct super_block *sb,
struct dentry *dentry);
static void exp_unexport_all(svc_client *clp);
static void exp_do_unexport(svc_export *unexp);
......@@ -66,40 +65,37 @@ static int want_lock;
static int hash_count;
static DECLARE_WAIT_QUEUE_HEAD( hash_wait );
/*
* Find a client's export for a device.
* Find the client's export entry matching xdev/xino.
*/
static inline svc_export *
exp_find(svc_client *clp, kdev_t dev)
svc_export *
exp_get(svc_client *clp, kdev_t dev, ino_t ino)
{
svc_export * exp;
exp = clp->cl_export[EXPORT_HASH(dev)];
while (exp && !kdev_same(exp->ex_dev, dev))
exp = exp->ex_next;
if (!clp)
return NULL;
for (exp = clp->cl_export[EXPORT_HASH(dev)]; exp; exp = exp->ex_next) {
if (exp->ex_ino == ino && kdev_same(exp->ex_dev, dev))
break;
}
return exp;
}
/*
* Find the client's export entry matching xdev/xino.
*/
svc_export *
exp_get(svc_client *clp, kdev_t dev, ino_t ino)
exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry)
{
svc_export * exp;
int hash = EXPORT_HASH(mnt->mnt_sb->s_dev);
svc_export *exp;
if (!clp)
return NULL;
exp = clp->cl_export[EXPORT_HASH(dev)];
if (exp)
do {
if (exp->ex_ino == ino && kdev_same(exp->ex_dev, dev))
goto out;
} while (NULL != (exp = exp->ex_next));
exp = NULL;
out:
for (exp = clp->cl_export[hash]; exp; exp = exp->ex_next) {
if (exp->ex_dentry == dentry && exp->ex_mnt == mnt)
break;
}
return exp;
}
......@@ -107,14 +103,14 @@ exp_get(svc_client *clp, kdev_t dev, ino_t ino)
* Find the export entry for a given dentry. <gam3@acm.org>
*/
static svc_export *
exp_parent(svc_client *clp, kdev_t dev, struct dentry *dentry)
exp_parent(svc_client *clp, struct super_block *sb, struct dentry *dentry)
{
svc_export *exp;
if (clp == NULL)
return NULL;
for (exp = clp->cl_export[EXPORT_HASH(dev)]; exp; exp = exp->ex_next)
for (exp = clp->cl_export[EXPORT_HASH(sb->s_dev)]; exp; exp = exp->ex_next)
if (is_subdir(dentry, exp->ex_dentry))
break;
return exp;
......@@ -126,14 +122,14 @@ exp_parent(svc_client *clp, kdev_t dev, struct dentry *dentry)
* <gam3@acm.org>
*/
static svc_export *
exp_child(svc_client *clp, kdev_t dev, struct dentry *dentry)
exp_child(svc_client *clp, struct super_block *sb, struct dentry *dentry)
{
svc_export *exp;
if (clp == NULL)
return NULL;
for (exp = clp->cl_export[EXPORT_HASH(dev)]; exp; exp = exp->ex_next) {
for (exp = clp->cl_export[EXPORT_HASH(sb->s_dev)]; exp; exp = exp->ex_next) {
struct dentry *ndentry = exp->ex_dentry;
if (ndentry && is_subdir(ndentry->d_parent, dentry))
break;
......@@ -221,12 +217,12 @@ exp_export(struct nfsctl_export *nxp)
goto finish;
}
if ((parent = exp_child(clp, dev, nd.dentry)) != NULL) {
if ((parent = exp_child(clp, inode->i_sb, nd.dentry)) != NULL) {
dprintk("exp_export: export not valid (Rule 3).\n");
goto finish;
}
/* Is this is a sub-export, must be a proper subset of FS */
if ((parent = exp_parent(clp, dev, nd.dentry)) != NULL) {
if ((parent = exp_parent(clp, inode->i_sb, nd.dentry)) != NULL) {
dprintk("exp_export: sub-export not valid (Rule 2).\n");
goto finish;
}
......@@ -380,55 +376,34 @@ exp_unexport(struct nfsctl_export *nxp)
* since its harder to fool a kernel module than a user space program.
*/
int
exp_rootfh(struct svc_client *clp, kdev_t dev, ino_t ino,
char *path, struct knfsd_fh *f, int maxsize)
exp_rootfh(struct svc_client *clp, char *path, struct knfsd_fh *f, int maxsize)
{
struct svc_export *exp;
struct nameidata nd;
struct inode *inode;
struct svc_fh fh;
kdev_t dev;
int err;
err = -EPERM;
if (path) {
if (path_init(path, LOOKUP_POSITIVE, &nd) &&
path_walk(path, &nd)) {
printk("nfsd: exp_rootfh path not found %s", path);
return err;
}
dev = nd.dentry->d_inode->i_dev;
ino = nd.dentry->d_inode->i_ino;
dprintk("nfsd: exp_rootfh(%s [%p] %s:%02x:%02x/%ld)\n",
path, nd.dentry, clp->cl_ident,
major(dev), minor(dev), (long) ino);
exp = exp_parent(clp, dev, nd.dentry);
} else {
dprintk("nfsd: exp_rootfh(%s:%02x:%02x/%ld)\n",
clp->cl_ident, major(dev), minor(dev), (long) ino);
if ((exp = exp_get(clp, dev, ino))) {
nd.mnt = mntget(exp->ex_mnt);
nd.dentry = dget(exp->ex_dentry);
}
/* NB: we probably ought to check that it's NUL-terminated */
if (path_init(path, LOOKUP_POSITIVE, &nd) &&
path_walk(path, &nd)) {
printk("nfsd: exp_rootfh path not found %s", path);
return err;
}
inode = nd.dentry->d_inode;
dev = inode->i_dev;
dprintk("nfsd: exp_rootfh(%s [%p] %s:%02x:%02x/%ld)\n",
path, nd.dentry, clp->cl_ident,
major(dev), minor(dev), (long) inode->i_ino);
exp = exp_parent(clp, inode->i_sb, nd.dentry);
if (!exp) {
dprintk("nfsd: exp_rootfh export not found.\n");
goto out;
}
inode = nd.dentry->d_inode;
if (!inode) {
printk("exp_rootfh: Aieee, NULL d_inode\n");
goto out;
}
if (!kdev_same(inode->i_dev, dev) || inode->i_ino != ino) {
printk("exp_rootfh: Aieee, ino/dev mismatch\n");
printk("exp_rootfh: arg[dev(%02x:%02x):ino(%ld)]"
" inode[dev(%02x:%02x):ino(%ld)]\n",
major(dev), minor(dev), (long) ino,
major(inode->i_dev), minor(inode->i_dev), (long) inode->i_ino);
}
/*
* fh must be initialized before calling fh_compose
*/
......
......@@ -37,7 +37,6 @@ static int nfsctl_addclient(struct nfsctl_client *data);
static int nfsctl_delclient(struct nfsctl_client *data);
static int nfsctl_export(struct nfsctl_export *data);
static int nfsctl_unexport(struct nfsctl_export *data);
static int nfsctl_getfh(struct nfsctl_fhparm *, __u8 *);
static int nfsctl_getfd(struct nfsctl_fdparm *, __u8 *);
static int nfsctl_getfs(struct nfsctl_fsparm *, struct knfsd_fh *);
#ifdef notyet
......@@ -125,7 +124,7 @@ nfsctl_getfs(struct nfsctl_fsparm *data, struct knfsd_fh *res)
if (!(clp = exp_getclient(sin)))
err = -EPERM;
else
err = exp_rootfh(clp, NODEV, 0, data->gd_path, res, data->gd_maxlen);
err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
exp_unlock();
return err;
}
......@@ -148,40 +147,7 @@ nfsctl_getfd(struct nfsctl_fdparm *data, __u8 *res)
if (!(clp = exp_getclient(sin)))
err = -EPERM;
else
err = exp_rootfh(clp, NODEV, 0, data->gd_path, &fh, NFS_FHSIZE);
exp_unlock();
if (err == 0) {
if (fh.fh_size > NFS_FHSIZE)
err = -EINVAL;
else {
memset(res,0, NFS_FHSIZE);
memcpy(res, &fh.fh_base, fh.fh_size);
}
}
return err;
}
static inline int
nfsctl_getfh(struct nfsctl_fhparm *data, __u8 *res)
{
struct sockaddr_in *sin;
struct svc_client *clp;
int err = 0;
struct knfsd_fh fh;
if (data->gf_addr.sa_family != AF_INET)
return -EPROTONOSUPPORT;
if (data->gf_version < 2 || data->gf_version > NFSSVC_MAXVERS)
return -EINVAL;
sin = (struct sockaddr_in *)&data->gf_addr;
exp_readlock();
if (!(clp = exp_getclient(sin)))
err = -EPERM;
else
err = exp_rootfh(clp, to_kdev_t(data->gf_dev), data->gf_ino, NULL, &fh, NFS_FHSIZE);
err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
exp_unlock();
if (err == 0) {
......@@ -277,9 +243,6 @@ asmlinkage handle_sys_nfsservctl(int cmd, void *opaque_argp, void *opaque_resp)
err = nfsctl_ugidupdate(&arg->ca_umap);
break;
#endif
case NFSCTL_GETFH:
err = nfsctl_getfh(&arg->ca_getfh, res->cr_getfh);
break;
case NFSCTL_GETFD:
err = nfsctl_getfd(&arg->ca_getfd, res->cr_getfh);
break;
......
......@@ -114,35 +114,30 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
if (isdotent(name, len)) {
if (len==1)
dentry = dget(dparent);
else { /* must be ".." */
else if (dparent != exp->ex_dentry)
dentry = dget(dparent->d_parent);
else if (!EX_CROSSMNT(exp))
dentry = dget(dparent); /* .. == . just like at / */
else {
/* checking mountpoint crossing is very different when stepping up */
if (dparent == exp->ex_dentry) {
if (!EX_CROSSMNT(exp))
dentry = dget(dparent); /* .. == . just like at / */
else
{
struct svc_export *exp2 = NULL;
struct dentry *dp;
struct vfsmount *mnt = mntget(exp->ex_mnt);
dentry = dget(dparent);
while(follow_up(&mnt, &dentry))
;
dp = dget(dentry->d_parent);
dput(dentry);
dentry = dp;
for ( ; exp2 == NULL && dp->d_parent != dp;
dp=dp->d_parent)
exp2 = exp_get(exp->ex_client, dp->d_inode->i_dev, dp->d_inode->i_ino);
if (exp2==NULL) {
dput(dentry);
dentry = dget(dparent);
} else {
exp = exp2;
}
mntput(mnt);
}
} else
dentry = dget(dparent->d_parent);
struct svc_export *exp2 = NULL;
struct dentry *dp;
struct vfsmount *mnt = mntget(exp->ex_mnt);
dentry = dget(dparent);
while(follow_up(&mnt, &dentry))
;
dp = dget(dentry->d_parent);
dput(dentry);
dentry = dp;
for ( ; !exp2 && dp->d_parent != dp; dp=dp->d_parent)
exp2 = exp_get_by_name(exp->ex_client, mnt, dp);
if (!exp2) {
dput(dentry);
dentry = dget(dparent);
} else {
exp = exp2;
}
mntput(mnt);
}
} else {
fh_lock(fhp);
......@@ -159,9 +154,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
struct dentry *mounts = dget(dentry);
while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts))
;
exp2 = exp_get(rqstp->rq_client,
mounts->d_inode->i_dev,
mounts->d_inode->i_ino);
exp2 = exp_get_by_name(rqstp->rq_client, mnt, mounts);
if (exp2 && EX_CROSSMNT(exp2)) {
/* successfully crossed mount point */
exp = exp2;
......@@ -591,6 +584,7 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
mm_segment_t oldfs;
int err;
struct file file;
struct inode *inode;
err = nfsd_open(rqstp, fhp, S_IFREG, MAY_READ, &file);
if (err)
......@@ -598,14 +592,15 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
err = nfserr_perm;
if (!file.f_op->read)
goto out_close;
inode = file.f_dentry->d_inode;
#ifdef MSNFS
if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
(!lock_may_read(file.f_dentry->d_inode, offset, *count)))
(!lock_may_read(inode, offset, *count)))
goto out_close;
#endif
/* Get readahead parameters */
ra = nfsd_get_raparms(fhp->fh_export->ex_dev, fhp->fh_dentry->d_inode->i_ino);
ra = nfsd_get_raparms(inode->i_dev, inode->i_ino);
if (ra) {
file.f_reada = ra->p_reada;
file.f_ramax = ra->p_ramax;
......
......@@ -1003,8 +1003,7 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry)
ei = PROC_I(inode);
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_ino = fake_ino(0, PROC_PID_INO);
ei->file = NULL;
ei->task = NULL;
ei->pde = NULL;
inode->i_mode = S_IFLNK|S_IRWXUGO;
inode->i_uid = inode->i_gid = 0;
inode->i_size = 64;
......
......@@ -90,7 +90,10 @@ void exp_unlock(void);
struct svc_client * exp_getclient(struct sockaddr_in *sin);
void exp_putclient(struct svc_client *clp);
struct svc_export * exp_get(struct svc_client *clp, kdev_t dev, ino_t ino);
int exp_rootfh(struct svc_client *, kdev_t, ino_t,
struct svc_export * exp_get_by_name(struct svc_client *clp,
struct vfsmount *mnt,
struct dentry *dentry);
int exp_rootfh(struct svc_client *,
char *path, struct knfsd_fh *, int maxsize);
int nfserrno(int errno);
void exp_nlmdetach(void);
......
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