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