Commit 1cc96096 authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[PATCH] PATCH 3 of 4 : knfsd : Store the fsid in the returned attributes...

[PATCH] PATCH 3 of 4 : knfsd : Store the fsid in the returned attributes instead of the device number

When a filesystem is exported with  fsid=  we should use that
fsid instead of the i_dev number when returning NFS attributes,
so that there is no chance of clients that depend on the filesys
id in the attributes getting confused by device numbers changing.

We only do this if the reference filehandle uses fsid to identify
the filesystem, so that a server can be converted from non-fsid= to
using fsid= without confusing active clients.
parent 09739cf7
...@@ -154,9 +154,9 @@ decode_sattr3(u32 *p, struct iattr *iap) ...@@ -154,9 +154,9 @@ decode_sattr3(u32 *p, struct iattr *iap)
} }
static inline u32 * static inline u32 *
encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct dentry *dentry) encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = fhp->fh_dentry->d_inode;
*p++ = htonl(nfs3_ftypes[(inode->i_mode & S_IFMT) >> 12]); *p++ = htonl(nfs3_ftypes[(inode->i_mode & S_IFMT) >> 12]);
*p++ = htonl((u32) inode->i_mode); *p++ = htonl((u32) inode->i_mode);
...@@ -175,6 +175,11 @@ encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct dentry *dentry) ...@@ -175,6 +175,11 @@ encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct dentry *dentry)
p = xdr_encode_hyper(p, ((u64)inode->i_blocks) << 9); p = xdr_encode_hyper(p, ((u64)inode->i_blocks) << 9);
*p++ = htonl((u32) major(inode->i_rdev)); *p++ = htonl((u32) major(inode->i_rdev));
*p++ = htonl((u32) minor(inode->i_rdev)); *p++ = htonl((u32) minor(inode->i_rdev));
if (rqstp->rq_reffh->fh_version == 1
&& rqstp->rq_reffh->fh_fsid_type == 1
&& (fhp->fh_export->ex_flags & NFSEXP_FSID))
p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
else
p = xdr_encode_hyper(p, (u64) kdev_t_to_nr(inode->i_dev)); p = xdr_encode_hyper(p, (u64) kdev_t_to_nr(inode->i_dev));
p = xdr_encode_hyper(p, (u64) inode->i_ino); p = xdr_encode_hyper(p, (u64) inode->i_ino);
p = encode_time3(p, inode->i_atime); p = encode_time3(p, inode->i_atime);
...@@ -205,6 +210,11 @@ encode_saved_post_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) ...@@ -205,6 +210,11 @@ encode_saved_post_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
p = xdr_encode_hyper(p, ((u64)fhp->fh_post_blocks) << 9); p = xdr_encode_hyper(p, ((u64)fhp->fh_post_blocks) << 9);
*p++ = htonl((u32) major(fhp->fh_post_rdev)); *p++ = htonl((u32) major(fhp->fh_post_rdev));
*p++ = htonl((u32) minor(fhp->fh_post_rdev)); *p++ = htonl((u32) minor(fhp->fh_post_rdev));
if (rqstp->rq_reffh->fh_version == 1
&& rqstp->rq_reffh->fh_fsid_type == 1
&& (fhp->fh_export->ex_flags & NFSEXP_FSID))
p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
else
p = xdr_encode_hyper(p, (u64) kdev_t_to_nr(inode->i_dev)); p = xdr_encode_hyper(p, (u64) kdev_t_to_nr(inode->i_dev));
p = xdr_encode_hyper(p, (u64) inode->i_ino); p = xdr_encode_hyper(p, (u64) inode->i_ino);
p = encode_time3(p, fhp->fh_post_atime); p = encode_time3(p, fhp->fh_post_atime);
...@@ -220,11 +230,12 @@ encode_saved_post_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) ...@@ -220,11 +230,12 @@ encode_saved_post_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
* handle. In this case, no attributes are returned. * handle. In this case, no attributes are returned.
*/ */
static u32 * static u32 *
encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct dentry *dentry) encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
{ {
struct dentry *dentry = fhp->fh_dentry;
if (dentry && dentry->d_inode != NULL) { if (dentry && dentry->d_inode != NULL) {
*p++ = xdr_one; /* attributes follow */ *p++ = xdr_one; /* attributes follow */
return encode_fattr3(rqstp, p, dentry); return encode_fattr3(rqstp, p, fhp);
} }
*p++ = xdr_zero; *p++ = xdr_zero;
return p; return p;
...@@ -251,7 +262,7 @@ encode_wcc_data(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) ...@@ -251,7 +262,7 @@ encode_wcc_data(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
} }
/* no pre- or post-attrs */ /* no pre- or post-attrs */
*p++ = xdr_zero; *p++ = xdr_zero;
return encode_post_op_attr(rqstp, p, dentry); return encode_post_op_attr(rqstp, p, fhp);
} }
/* /*
...@@ -509,7 +520,7 @@ nfs3svc_encode_attrstat(struct svc_rqst *rqstp, u32 *p, ...@@ -509,7 +520,7 @@ nfs3svc_encode_attrstat(struct svc_rqst *rqstp, u32 *p,
struct nfsd3_attrstat *resp) struct nfsd3_attrstat *resp)
{ {
if (resp->status == 0) if (resp->status == 0)
p = encode_fattr3(rqstp, p, resp->fh.fh_dentry); p = encode_fattr3(rqstp, p, &resp->fh);
return xdr_ressize_check(rqstp, p); return xdr_ressize_check(rqstp, p);
} }
...@@ -529,9 +540,9 @@ nfs3svc_encode_diropres(struct svc_rqst *rqstp, u32 *p, ...@@ -529,9 +540,9 @@ nfs3svc_encode_diropres(struct svc_rqst *rqstp, u32 *p,
{ {
if (resp->status == 0) { if (resp->status == 0) {
p = encode_fh(p, &resp->fh); p = encode_fh(p, &resp->fh);
p = encode_post_op_attr(rqstp, p, resp->fh.fh_dentry); p = encode_post_op_attr(rqstp, p, &resp->fh);
} }
p = encode_post_op_attr(rqstp, p, resp->dirfh.fh_dentry); p = encode_post_op_attr(rqstp, p, &resp->dirfh);
return xdr_ressize_check(rqstp, p); return xdr_ressize_check(rqstp, p);
} }
...@@ -540,7 +551,7 @@ int ...@@ -540,7 +551,7 @@ int
nfs3svc_encode_accessres(struct svc_rqst *rqstp, u32 *p, nfs3svc_encode_accessres(struct svc_rqst *rqstp, u32 *p,
struct nfsd3_accessres *resp) struct nfsd3_accessres *resp)
{ {
p = encode_post_op_attr(rqstp, p, resp->fh.fh_dentry); p = encode_post_op_attr(rqstp, p, &resp->fh);
if (resp->status == 0) if (resp->status == 0)
*p++ = htonl(resp->access); *p++ = htonl(resp->access);
return xdr_ressize_check(rqstp, p); return xdr_ressize_check(rqstp, p);
...@@ -551,7 +562,7 @@ int ...@@ -551,7 +562,7 @@ int
nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p, nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p,
struct nfsd3_readlinkres *resp) struct nfsd3_readlinkres *resp)
{ {
p = encode_post_op_attr(rqstp, p, resp->fh.fh_dentry); p = encode_post_op_attr(rqstp, p, &resp->fh);
if (resp->status == 0) { if (resp->status == 0) {
*p++ = htonl(resp->len); *p++ = htonl(resp->len);
p += XDR_QUADLEN(resp->len); p += XDR_QUADLEN(resp->len);
...@@ -564,7 +575,7 @@ int ...@@ -564,7 +575,7 @@ int
nfs3svc_encode_readres(struct svc_rqst *rqstp, u32 *p, nfs3svc_encode_readres(struct svc_rqst *rqstp, u32 *p,
struct nfsd3_readres *resp) struct nfsd3_readres *resp)
{ {
p = encode_post_op_attr(rqstp, p, resp->fh.fh_dentry); p = encode_post_op_attr(rqstp, p, &resp->fh);
if (resp->status == 0) { if (resp->status == 0) {
*p++ = htonl(resp->count); *p++ = htonl(resp->count);
*p++ = htonl(resp->eof); *p++ = htonl(resp->eof);
...@@ -597,7 +608,7 @@ nfs3svc_encode_createres(struct svc_rqst *rqstp, u32 *p, ...@@ -597,7 +608,7 @@ nfs3svc_encode_createres(struct svc_rqst *rqstp, u32 *p,
if (resp->status == 0) { if (resp->status == 0) {
*p++ = xdr_one; *p++ = xdr_one;
p = encode_fh(p, &resp->fh); p = encode_fh(p, &resp->fh);
p = encode_post_op_attr(rqstp, p, resp->fh.fh_dentry); p = encode_post_op_attr(rqstp, p, &resp->fh);
} }
p = encode_wcc_data(rqstp, p, &resp->dirfh); p = encode_wcc_data(rqstp, p, &resp->dirfh);
return xdr_ressize_check(rqstp, p); return xdr_ressize_check(rqstp, p);
...@@ -618,7 +629,7 @@ int ...@@ -618,7 +629,7 @@ int
nfs3svc_encode_linkres(struct svc_rqst *rqstp, u32 *p, nfs3svc_encode_linkres(struct svc_rqst *rqstp, u32 *p,
struct nfsd3_linkres *resp) struct nfsd3_linkres *resp)
{ {
p = encode_post_op_attr(rqstp, p, resp->fh.fh_dentry); p = encode_post_op_attr(rqstp, p, &resp->fh);
p = encode_wcc_data(rqstp, p, &resp->tfh); p = encode_wcc_data(rqstp, p, &resp->tfh);
return xdr_ressize_check(rqstp, p); return xdr_ressize_check(rqstp, p);
} }
...@@ -628,7 +639,7 @@ int ...@@ -628,7 +639,7 @@ int
nfs3svc_encode_readdirres(struct svc_rqst *rqstp, u32 *p, nfs3svc_encode_readdirres(struct svc_rqst *rqstp, u32 *p,
struct nfsd3_readdirres *resp) struct nfsd3_readdirres *resp)
{ {
p = encode_post_op_attr(rqstp, p, resp->fh.fh_dentry); p = encode_post_op_attr(rqstp, p, &resp->fh);
if (resp->status == 0) { if (resp->status == 0) {
/* stupid readdir cookie */ /* stupid readdir cookie */
memcpy(p, resp->verf, 8); p += 2; memcpy(p, resp->verf, 8); p += 2;
...@@ -711,7 +722,7 @@ encode_entry(struct readdir_cd *cd, const char *name, ...@@ -711,7 +722,7 @@ encode_entry(struct readdir_cd *cd, const char *name,
goto noexec; goto noexec;
if (fh_compose(&fh, exp, dchild, cd->dirfh) != 0 || !dchild->d_inode) if (fh_compose(&fh, exp, dchild, cd->dirfh) != 0 || !dchild->d_inode)
goto noexec; goto noexec;
p = encode_post_op_attr(cd->rqstp, p, fh.fh_dentry); p = encode_post_op_attr(cd->rqstp, p, &fh);
*p++ = xdr_one; /* yes, a file handle follows */ *p++ = xdr_one; /* yes, a file handle follows */
p = encode_fh(p, &fh); p = encode_fh(p, &fh);
fh_put(&fh); fh_put(&fh);
......
...@@ -546,6 +546,9 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) ...@@ -546,6 +546,9 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp)); dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
/* keep this filehandle for possible reference when encoding attributes */
rqstp->rq_reffh = fhp;
if (!fhp->fh_dentry) { if (!fhp->fh_dentry) {
kdev_t xdev = NODEV; kdev_t xdev = NODEV;
ino_t xino = 0; ino_t xino = 0;
......
...@@ -132,8 +132,9 @@ decode_sattr(u32 *p, struct iattr *iap) ...@@ -132,8 +132,9 @@ decode_sattr(u32 *p, struct iattr *iap)
} }
static inline u32 * static inline u32 *
encode_fattr(struct svc_rqst *rqstp, u32 *p, struct inode *inode) encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
{ {
struct inode *inode = fhp->fh_dentry->d_inode;
int type = (inode->i_mode & S_IFMT); int type = (inode->i_mode & S_IFMT);
*p++ = htonl(nfs_ftypes[type >> 12]); *p++ = htonl(nfs_ftypes[type >> 12]);
...@@ -153,6 +154,11 @@ encode_fattr(struct svc_rqst *rqstp, u32 *p, struct inode *inode) ...@@ -153,6 +154,11 @@ encode_fattr(struct svc_rqst *rqstp, u32 *p, struct inode *inode)
else else
*p++ = htonl(0xffffffff); *p++ = htonl(0xffffffff);
*p++ = htonl((u32) inode->i_blocks); *p++ = htonl((u32) inode->i_blocks);
if (rqstp->rq_reffh->fh_version == 1
&& rqstp->rq_reffh->fh_fsid_type == 1
&& (fhp->fh_export->ex_flags & NFSEXP_FSID))
*p++ = htonl((u32) fhp->fh_export->ex_fsid);
else
*p++ = htonl((u32) kdev_t_to_nr(inode->i_dev)); *p++ = htonl((u32) kdev_t_to_nr(inode->i_dev));
*p++ = htonl((u32) inode->i_ino); *p++ = htonl((u32) inode->i_ino);
*p++ = htonl((u32) inode->i_atime); *p++ = htonl((u32) inode->i_atime);
...@@ -332,7 +338,7 @@ int ...@@ -332,7 +338,7 @@ int
nfssvc_encode_attrstat(struct svc_rqst *rqstp, u32 *p, nfssvc_encode_attrstat(struct svc_rqst *rqstp, u32 *p,
struct nfsd_attrstat *resp) struct nfsd_attrstat *resp)
{ {
p = encode_fattr(rqstp, p, resp->fh.fh_dentry->d_inode); p = encode_fattr(rqstp, p, &resp->fh);
return xdr_ressize_check(rqstp, p); return xdr_ressize_check(rqstp, p);
} }
...@@ -341,7 +347,7 @@ nfssvc_encode_diropres(struct svc_rqst *rqstp, u32 *p, ...@@ -341,7 +347,7 @@ nfssvc_encode_diropres(struct svc_rqst *rqstp, u32 *p,
struct nfsd_diropres *resp) struct nfsd_diropres *resp)
{ {
p = encode_fh(p, &resp->fh); p = encode_fh(p, &resp->fh);
p = encode_fattr(rqstp, p, resp->fh.fh_dentry->d_inode); p = encode_fattr(rqstp, p, &resp->fh);
return xdr_ressize_check(rqstp, p); return xdr_ressize_check(rqstp, p);
} }
...@@ -358,7 +364,7 @@ int ...@@ -358,7 +364,7 @@ int
nfssvc_encode_readres(struct svc_rqst *rqstp, u32 *p, nfssvc_encode_readres(struct svc_rqst *rqstp, u32 *p,
struct nfsd_readres *resp) struct nfsd_readres *resp)
{ {
p = encode_fattr(rqstp, p, resp->fh.fh_dentry->d_inode); p = encode_fattr(rqstp, p, &resp->fh);
*p++ = htonl(resp->count); *p++ = htonl(resp->count);
p += XDR_QUADLEN(resp->count); p += XDR_QUADLEN(resp->count);
......
...@@ -123,6 +123,10 @@ struct svc_rqst { ...@@ -123,6 +123,10 @@ struct svc_rqst {
/* Catering to nfsd */ /* Catering to nfsd */
struct svc_client * rq_client; /* RPC peer info */ struct svc_client * rq_client; /* RPC peer info */
struct svc_cacherep * rq_cacherep; /* cache info */ struct svc_cacherep * rq_cacherep; /* cache info */
struct knfsd_fh * rq_reffh; /* Referrence filehandle, used to
* determine what device number
* to report (real or virtual)
*/
wait_queue_head_t rq_wait; /* synchronozation */ wait_queue_head_t rq_wait; /* synchronozation */
}; };
......
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