]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.fixes/nfs-fix-posix-acl
Updated xen patches taken from suse.
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.fixes / nfs-fix-posix-acl
1 From: Trond Myklebust <Trond.Myklebust@netapp.com>
2 Subject: NFSv3: Fix posix ACL code
3 References: 465854
4 Patch-mainline: 2.6.29-rc7
5
6 Upstream 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
17 Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
18 Signed-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
27 Index: 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 }
93 Index: 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) ?
148 Index: 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
161 Index: 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 {