diff options
author | J. Bruce Fields <bfields@redhat.com> | 2014-03-10 12:19:10 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2014-05-30 17:31:55 -0400 |
commit | 8c7424cff6bd33459945646cfcbf6dc6c899ab24 (patch) | |
tree | b407f5e3603364585e1116cf9300b449a262a85b /fs/nfsd | |
parent | f5236013a21c118e9d317e90c7a152dfe51fab93 (diff) |
nfsd4: don't try to encode conflicting owner if low on space
I ran into this corner case in testing: in theory clients can provide
state owners up to 1024 bytes long. In the sessions case there might be
a risk of this pushing us over the DRC slot size.
The conflicting owner isn't really that important, so let's humor a
client that provides a small maxresponsize_cached by allowing ourselves
to return without the conflicting owner instead of outright failing the
operation.
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/nfs4proc.c | 3 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 16 |
2 files changed, 15 insertions, 4 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 5d8f9158701d..20aad5a3005f 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -1432,7 +1432,8 @@ out: | |||
1432 | #define op_encode_change_info_maxsz (5) | 1432 | #define op_encode_change_info_maxsz (5) |
1433 | #define nfs4_fattr_bitmap_maxsz (4) | 1433 | #define nfs4_fattr_bitmap_maxsz (4) |
1434 | 1434 | ||
1435 | #define op_encode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) | 1435 | /* We'll fall back on returning no lockowner if run out of space: */ |
1436 | #define op_encode_lockowner_maxsz (0) | ||
1436 | #define op_encode_lock_denied_maxsz (8 + op_encode_lockowner_maxsz) | 1437 | #define op_encode_lock_denied_maxsz (8 + op_encode_lockowner_maxsz) |
1437 | 1438 | ||
1438 | #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) | 1439 | #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index a90a1e86614a..2f0ea20edb23 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -2878,9 +2878,20 @@ nfsd4_encode_lock_denied(struct xdr_stream *xdr, struct nfsd4_lock_denied *ld) | |||
2878 | struct xdr_netobj *conf = &ld->ld_owner; | 2878 | struct xdr_netobj *conf = &ld->ld_owner; |
2879 | __be32 *p; | 2879 | __be32 *p; |
2880 | 2880 | ||
2881 | again: | ||
2881 | p = xdr_reserve_space(xdr, 32 + XDR_LEN(conf->len)); | 2882 | p = xdr_reserve_space(xdr, 32 + XDR_LEN(conf->len)); |
2882 | if (!p) | 2883 | if (!p) { |
2884 | /* | ||
2885 | * Don't fail to return the result just because we can't | ||
2886 | * return the conflicting open: | ||
2887 | */ | ||
2888 | if (conf->len) { | ||
2889 | conf->len = 0; | ||
2890 | conf->data = NULL; | ||
2891 | goto again; | ||
2892 | } | ||
2883 | return nfserr_resource; | 2893 | return nfserr_resource; |
2894 | } | ||
2884 | WRITE64(ld->ld_start); | 2895 | WRITE64(ld->ld_start); |
2885 | WRITE64(ld->ld_length); | 2896 | WRITE64(ld->ld_length); |
2886 | WRITE32(ld->ld_type); | 2897 | WRITE32(ld->ld_type); |
@@ -2888,7 +2899,6 @@ nfsd4_encode_lock_denied(struct xdr_stream *xdr, struct nfsd4_lock_denied *ld) | |||
2888 | WRITEMEM(&ld->ld_clientid, 8); | 2899 | WRITEMEM(&ld->ld_clientid, 8); |
2889 | WRITE32(conf->len); | 2900 | WRITE32(conf->len); |
2890 | WRITEMEM(conf->data, conf->len); | 2901 | WRITEMEM(conf->data, conf->len); |
2891 | kfree(conf->data); | ||
2892 | } else { /* non - nfsv4 lock in conflict, no clientid nor owner */ | 2902 | } else { /* non - nfsv4 lock in conflict, no clientid nor owner */ |
2893 | WRITE64((u64)0); /* clientid */ | 2903 | WRITE64((u64)0); /* clientid */ |
2894 | WRITE32(0); /* length of owner name */ | 2904 | WRITE32(0); /* length of owner name */ |
@@ -2905,7 +2915,7 @@ nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lo | |||
2905 | nfserr = nfsd4_encode_stateid(xdr, &lock->lk_resp_stateid); | 2915 | nfserr = nfsd4_encode_stateid(xdr, &lock->lk_resp_stateid); |
2906 | else if (nfserr == nfserr_denied) | 2916 | else if (nfserr == nfserr_denied) |
2907 | nfserr = nfsd4_encode_lock_denied(xdr, &lock->lk_denied); | 2917 | nfserr = nfsd4_encode_lock_denied(xdr, &lock->lk_denied); |
2908 | 2918 | kfree(lock->lk_denied.ld_owner.data); | |
2909 | return nfserr; | 2919 | return nfserr; |
2910 | } | 2920 | } |
2911 | 2921 | ||