]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.25/patches.fixes/nfs-fix-posix-acl
Reenabled linux-xen and xen-image build
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.fixes / nfs-fix-posix-acl
CommitLineData
00e5a55c
BS
1From: Trond Myklebust <Trond.Myklebust@netapp.com>
2Subject: NFSv3: Fix posix ACL code
3References: 465854
4Patch-mainline: 2.6.29-rc7
5
6Upstream commit ae46141ff08f1965b17c531b571953c39ce8b9e2.
7
8 Fix a memory leak due to allocation in the XDR layer. In cases where the
9 RPC call needs to be retransmitted, we end up allocating new pages without
10 clearing the old ones. Fix this by moving the allocation into
11 nfs3_proc_setacls().
12
13 Also fix an issue discovered by Kevin Rudd, whereby the amount of memory
14 reserved for the acls in the xdr_buf->head was miscalculated, and causing
15 corruption.
16
17Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
18Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
19---
20
21 fs/nfs/nfs3acl.c | 27 +++++++++++++++++++++------
22 fs/nfs/nfs3xdr.c | 34 +++++++++++++---------------------
23 include/linux/nfs_xdr.h | 2 ++
24 include/linux/nfsacl.h | 3 +++
25 4 files changed, 39 insertions(+), 27 deletions(-)
26
27Index: linux-2.6.27-SLE11_BRANCH/fs/nfs/nfs3acl.c
28===================================================================
29--- linux-2.6.27-SLE11_BRANCH.orig/fs/nfs/nfs3acl.c
30+++ linux-2.6.27-SLE11_BRANCH/fs/nfs/nfs3acl.c
31@@ -291,7 +291,7 @@ static int nfs3_proc_setacls(struct inod
32 {
33 struct nfs_server *server = NFS_SERVER(inode);
34 struct nfs_fattr fattr;
35- struct page *pages[NFSACL_MAXPAGES] = { };
36+ struct page *pages[NFSACL_MAXPAGES];
37 struct nfs3_setaclargs args = {
38 .inode = inode,
39 .mask = NFS_ACL,
40@@ -302,7 +302,7 @@ static int nfs3_proc_setacls(struct inod
41 .rpc_argp = &args,
42 .rpc_resp = &fattr,
43 };
44- int status, count;
45+ int status;
46
47 status = -EOPNOTSUPP;
48 if (!nfs_server_capable(inode, NFS_CAP_ACLS))
49@@ -318,6 +318,20 @@ static int nfs3_proc_setacls(struct inod
50 if (S_ISDIR(inode->i_mode)) {
51 args.mask |= NFS_DFACL;
52 args.acl_default = dfacl;
53+ args.len = nfsacl_size(acl, dfacl);
54+ } else
55+ args.len = nfsacl_size(acl, NULL);
56+
57+ if (args.len > NFS_ACL_INLINE_BUFSIZE) {
58+ unsigned int npages = 1 + ((args.len - 1) >> PAGE_SHIFT);
59+
60+ status = -ENOMEM;
61+ do {
62+ args.pages[args.npages] = alloc_page(GFP_KERNEL);
63+ if (args.pages[args.npages] == NULL)
64+ goto out_freepages;
65+ args.npages++;
66+ } while (args.npages < npages);
67 }
68
69 dprintk("NFS call setacl\n");
70@@ -327,10 +341,6 @@ static int nfs3_proc_setacls(struct inod
71 nfs_zap_acl_cache(inode);
72 dprintk("NFS reply setacl: %d\n", status);
73
74- /* pages may have been allocated at the xdr layer. */
75- for (count = 0; count < NFSACL_MAXPAGES && args.pages[count]; count++)
76- __free_page(args.pages[count]);
77-
78 switch (status) {
79 case 0:
80 status = nfs_refresh_inode(inode, &fattr);
81@@ -344,6 +354,11 @@ static int nfs3_proc_setacls(struct inod
82 case -ENOTSUPP:
83 status = -EOPNOTSUPP;
84 }
85+out_freepages:
86+ while (args.npages != 0) {
87+ args.npages--;
88+ __free_page(args.pages[args.npages]);
89+ }
90 out:
91 return status;
92 }
93Index: linux-2.6.27-SLE11_BRANCH/fs/nfs/nfs3xdr.c
94===================================================================
95--- linux-2.6.27-SLE11_BRANCH.orig/fs/nfs/nfs3xdr.c
96+++ linux-2.6.27-SLE11_BRANCH/fs/nfs/nfs3xdr.c
97@@ -82,8 +82,10 @@
98 #define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2)
99
100 #define ACL3_getaclargs_sz (NFS3_fh_sz+1)
101-#define ACL3_setaclargs_sz (NFS3_fh_sz+1+2*(2+5*3))
102-#define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+2*(2+5*3))
103+#define ACL3_setaclargs_sz (NFS3_fh_sz+1+ \
104+ XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
105+#define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+ \
106+ XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
107 #define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz)
108
109 /*
110@@ -703,28 +705,18 @@ nfs3_xdr_setaclargs(struct rpc_rqst *req
111 struct nfs3_setaclargs *args)
112 {
113 struct xdr_buf *buf = &req->rq_snd_buf;
114- unsigned int base, len_in_head, len = nfsacl_size(
115- (args->mask & NFS_ACL) ? args->acl_access : NULL,
116- (args->mask & NFS_DFACL) ? args->acl_default : NULL);
117- int count, err;
118+ unsigned int base;
119+ int err;
120
121 p = xdr_encode_fhandle(p, NFS_FH(args->inode));
122 *p++ = htonl(args->mask);
123- base = (char *)p - (char *)buf->head->iov_base;
124- /* put as much of the acls into head as possible. */
125- len_in_head = min_t(unsigned int, buf->head->iov_len - base, len);
126- len -= len_in_head;
127- req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + (len_in_head >> 2));
128-
129- for (count = 0; (count << PAGE_SHIFT) < len; count++) {
130- args->pages[count] = alloc_page(GFP_KERNEL);
131- if (!args->pages[count]) {
132- while (count)
133- __free_page(args->pages[--count]);
134- return -ENOMEM;
135- }
136- }
137- xdr_encode_pages(buf, args->pages, 0, len);
138+ req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
139+ base = req->rq_slen;
140+
141+ if (args->npages != 0)
142+ xdr_encode_pages(buf, args->pages, 0, args->len);
143+ else
144+ req->rq_slen += args->len;
145
146 err = nfsacl_encode(buf, base, args->inode,
147 (args->mask & NFS_ACL) ?
148Index: linux-2.6.27-SLE11_BRANCH/include/linux/nfs_xdr.h
149===================================================================
150--- linux-2.6.27-SLE11_BRANCH.orig/include/linux/nfs_xdr.h
151+++ linux-2.6.27-SLE11_BRANCH/include/linux/nfs_xdr.h
152@@ -404,6 +404,8 @@ struct nfs3_setaclargs {
153 int mask;
154 struct posix_acl * acl_access;
155 struct posix_acl * acl_default;
156+ size_t len;
157+ unsigned int npages;
158 struct page ** pages;
159 };
160
161Index: linux-2.6.27-SLE11_BRANCH/include/linux/nfsacl.h
162===================================================================
163--- linux-2.6.27-SLE11_BRANCH.orig/include/linux/nfsacl.h
164+++ linux-2.6.27-SLE11_BRANCH/include/linux/nfsacl.h
165@@ -37,6 +37,9 @@
166 #define NFSACL_MAXPAGES ((2*(8+12*NFS_ACL_MAX_ENTRIES) + PAGE_SIZE-1) \
167 >> PAGE_SHIFT)
168
169+#define NFS_ACL_MAX_ENTRIES_INLINE (5)
170+#define NFS_ACL_INLINE_BUFSIZE ((2*(2+3*NFS_ACL_MAX_ENTRIES_INLINE)) << 2)
171+
172 static inline unsigned int
173 nfsacl_size(struct posix_acl *acl_access, struct posix_acl *acl_default)
174 {