]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Tiger Yang <tiger.yang@oracle.com> |
2 | Date: Fri, 14 Nov 2008 11:17:41 +0800 | |
3 | Subject: ocfs2: add ocfs2_init_acl in mknod | |
4 | Patch-mainline: 2.6.29 | |
5 | ||
6 | We need to get the parent directories acls and let the new child inherit it. | |
7 | To this, we add additional calculations for data/metadata allocation. | |
8 | ||
9 | Signed-off-by: Tiger Yang <tiger.yang@oracle.com> | |
10 | Signed-off-by: Mark Fasheh <mfasheh@suse.com> | |
11 | --- | |
12 | fs/ocfs2/acl.c | 59 ++++++++++++++++++++++++++++++++++++++++ | |
13 | fs/ocfs2/acl.h | 14 +++++++++ | |
14 | fs/ocfs2/namei.c | 23 ++++++++++----- | |
15 | fs/ocfs2/xattr.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
16 | fs/ocfs2/xattr.h | 3 ++ | |
17 | 5 files changed, 170 insertions(+), 8 deletions(-) | |
18 | ||
19 | diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c | |
20 | index df72256..12dfb44 100644 | |
21 | --- a/fs/ocfs2/acl.c | |
22 | +++ b/fs/ocfs2/acl.c | |
23 | @@ -272,6 +272,65 @@ int ocfs2_acl_chmod(struct inode *inode) | |
24 | return ret; | |
25 | } | |
26 | ||
27 | +/* | |
28 | + * Initialize the ACLs of a new inode. If parent directory has default ACL, | |
29 | + * then clone to new inode. Called from ocfs2_mknod. | |
30 | + */ | |
31 | +int ocfs2_init_acl(handle_t *handle, | |
32 | + struct inode *inode, | |
33 | + struct inode *dir, | |
34 | + struct buffer_head *di_bh, | |
35 | + struct buffer_head *dir_bh, | |
36 | + struct ocfs2_alloc_context *meta_ac, | |
37 | + struct ocfs2_alloc_context *data_ac) | |
38 | +{ | |
39 | + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | |
40 | + struct posix_acl *acl = NULL; | |
41 | + int ret = 0; | |
42 | + | |
43 | + if (!S_ISLNK(inode->i_mode)) { | |
44 | + if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) { | |
45 | + acl = ocfs2_get_acl_nolock(dir, ACL_TYPE_DEFAULT, | |
46 | + dir_bh); | |
47 | + if (IS_ERR(acl)) | |
48 | + return PTR_ERR(acl); | |
49 | + } | |
50 | + if (!acl) | |
51 | + inode->i_mode &= ~current->fs->umask; | |
52 | + } | |
53 | + if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) { | |
54 | + struct posix_acl *clone; | |
55 | + mode_t mode; | |
56 | + | |
57 | + if (S_ISDIR(inode->i_mode)) { | |
58 | + ret = ocfs2_set_acl(handle, inode, di_bh, | |
59 | + ACL_TYPE_DEFAULT, acl, | |
60 | + meta_ac, data_ac); | |
61 | + if (ret) | |
62 | + goto cleanup; | |
63 | + } | |
64 | + clone = posix_acl_clone(acl, GFP_NOFS); | |
65 | + ret = -ENOMEM; | |
66 | + if (!clone) | |
67 | + goto cleanup; | |
68 | + | |
69 | + mode = inode->i_mode; | |
70 | + ret = posix_acl_create_masq(clone, &mode); | |
71 | + if (ret >= 0) { | |
72 | + inode->i_mode = mode; | |
73 | + if (ret > 0) { | |
74 | + ret = ocfs2_set_acl(handle, inode, | |
75 | + di_bh, ACL_TYPE_ACCESS, | |
76 | + clone, meta_ac, data_ac); | |
77 | + } | |
78 | + } | |
79 | + posix_acl_release(clone); | |
80 | + } | |
81 | +cleanup: | |
82 | + posix_acl_release(acl); | |
83 | + return ret; | |
84 | +} | |
85 | + | |
86 | static size_t ocfs2_xattr_list_acl_access(struct inode *inode, | |
87 | char *list, | |
88 | size_t list_len, | |
89 | diff --git a/fs/ocfs2/acl.h b/fs/ocfs2/acl.h | |
90 | index 68ffd64..8f6389e 100644 | |
91 | --- a/fs/ocfs2/acl.h | |
92 | +++ b/fs/ocfs2/acl.h | |
93 | @@ -30,6 +30,10 @@ struct ocfs2_acl_entry { | |
94 | ||
95 | extern int ocfs2_check_acl(struct inode *, int); | |
96 | extern int ocfs2_acl_chmod(struct inode *); | |
97 | +extern int ocfs2_init_acl(handle_t *, struct inode *, struct inode *, | |
98 | + struct buffer_head *, struct buffer_head *, | |
99 | + struct ocfs2_alloc_context *, | |
100 | + struct ocfs2_alloc_context *); | |
101 | ||
102 | #else /* CONFIG_OCFS2_FS_POSIX_ACL*/ | |
103 | ||
104 | @@ -38,6 +42,16 @@ static inline int ocfs2_acl_chmod(struct inode *inode) | |
105 | { | |
106 | return 0; | |
107 | } | |
108 | +static inline int ocfs2_init_acl(handle_t *handle, | |
109 | + struct inode *inode, | |
110 | + struct inode *dir, | |
111 | + struct buffer_head *di_bh, | |
112 | + struct buffer_head *dir_bh, | |
113 | + struct ocfs2_alloc_context *meta_ac, | |
114 | + struct ocfs2_alloc_context *data_ac) | |
115 | +{ | |
116 | + return 0; | |
117 | +} | |
118 | ||
119 | #endif /* CONFIG_OCFS2_FS_POSIX_ACL*/ | |
120 | ||
121 | diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c | |
122 | index 40da46b..7655145 100644 | |
123 | --- a/fs/ocfs2/namei.c | |
124 | +++ b/fs/ocfs2/namei.c | |
125 | @@ -61,6 +61,7 @@ | |
126 | #include "sysfile.h" | |
127 | #include "uptodate.h" | |
128 | #include "xattr.h" | |
129 | +#include "acl.h" | |
130 | ||
131 | #include "buffer_head_io.h" | |
132 | ||
133 | @@ -302,14 +303,13 @@ static int ocfs2_mknod(struct inode *dir, | |
134 | } | |
135 | } | |
136 | ||
137 | - /* calculate meta data/clusters for setting security xattr */ | |
138 | - if (si.enable) { | |
139 | - status = ocfs2_calc_security_init(dir, &si, &want_clusters, | |
140 | - &xattr_credits, &xattr_ac); | |
141 | - if (status < 0) { | |
142 | - mlog_errno(status); | |
143 | - goto leave; | |
144 | - } | |
145 | + /* calculate meta data/clusters for setting security and acl xattr */ | |
146 | + status = ocfs2_calc_xattr_init(dir, parent_fe_bh, mode, | |
147 | + &si, &want_clusters, | |
148 | + &xattr_credits, &xattr_ac); | |
149 | + if (status < 0) { | |
150 | + mlog_errno(status); | |
151 | + goto leave; | |
152 | } | |
153 | ||
154 | /* Reserve a cluster if creating an extent based directory. */ | |
155 | @@ -363,6 +363,13 @@ static int ocfs2_mknod(struct inode *dir, | |
156 | inc_nlink(dir); | |
157 | } | |
158 | ||
159 | + status = ocfs2_init_acl(handle, inode, dir, new_fe_bh, parent_fe_bh, | |
160 | + xattr_ac, data_ac); | |
161 | + if (status < 0) { | |
162 | + mlog_errno(status); | |
163 | + goto leave; | |
164 | + } | |
165 | + | |
166 | if (si.enable) { | |
167 | status = ocfs2_init_security_set(handle, inode, new_fe_bh, &si, | |
168 | xattr_ac, data_ac); | |
169 | diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c | |
170 | index 2e273c2..3cc8385 100644 | |
171 | --- a/fs/ocfs2/xattr.c | |
172 | +++ b/fs/ocfs2/xattr.c | |
173 | @@ -84,6 +84,10 @@ struct ocfs2_xattr_set_ctxt { | |
174 | #define OCFS2_XATTR_FREE_IN_IBODY (OCFS2_MIN_XATTR_INLINE_SIZE \ | |
175 | - sizeof(struct ocfs2_xattr_header) \ | |
176 | - sizeof(__u32)) | |
177 | +#define OCFS2_XATTR_FREE_IN_BLOCK(ptr) ((ptr)->i_sb->s_blocksize \ | |
178 | + - sizeof(struct ocfs2_xattr_block) \ | |
179 | + - sizeof(struct ocfs2_xattr_header) \ | |
180 | + - sizeof(__u32)) | |
181 | ||
182 | static struct ocfs2_xattr_def_value_root def_xv = { | |
183 | .xv.xr_list.l_count = cpu_to_le16(1), | |
184 | @@ -402,6 +406,81 @@ int ocfs2_calc_security_init(struct inode *dir, | |
185 | return ret; | |
186 | } | |
187 | ||
188 | +int ocfs2_calc_xattr_init(struct inode *dir, | |
189 | + struct buffer_head *dir_bh, | |
190 | + int mode, | |
191 | + struct ocfs2_security_xattr_info *si, | |
192 | + int *want_clusters, | |
193 | + int *xattr_credits, | |
194 | + struct ocfs2_alloc_context **xattr_ac) | |
195 | +{ | |
196 | + int ret = 0; | |
197 | + struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); | |
198 | + int s_size = 0; | |
199 | + int a_size = 0; | |
200 | + int acl_len = 0; | |
201 | + | |
202 | + if (si->enable) | |
203 | + s_size = ocfs2_xattr_entry_real_size(strlen(si->name), | |
204 | + si->value_len); | |
205 | + | |
206 | + if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) { | |
207 | + acl_len = ocfs2_xattr_get_nolock(dir, dir_bh, | |
208 | + OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT, | |
209 | + "", NULL, 0); | |
210 | + if (acl_len > 0) { | |
211 | + a_size = ocfs2_xattr_entry_real_size(0, acl_len); | |
212 | + if (S_ISDIR(mode)) | |
213 | + a_size <<= 1; | |
214 | + } else if (acl_len != 0 && acl_len != -ENODATA) { | |
215 | + mlog_errno(ret); | |
216 | + return ret; | |
217 | + } | |
218 | + } | |
219 | + | |
220 | + if (!(s_size + a_size)) | |
221 | + return ret; | |
222 | + | |
223 | + /* | |
224 | + * The max space of security xattr taken inline is | |
225 | + * 256(name) + 80(value) + 16(entry) = 352 bytes, | |
226 | + * The max space of acl xattr taken inline is | |
227 | + * 80(value) + 16(entry) * 2(if directory) = 192 bytes, | |
228 | + * when blocksize = 512, may reserve one more cluser for | |
229 | + * xattr bucket, otherwise reserve one metadata block | |
230 | + * for them is ok. | |
231 | + */ | |
232 | + if (dir->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE || | |
233 | + (s_size + a_size) > OCFS2_XATTR_FREE_IN_IBODY) { | |
234 | + ret = ocfs2_reserve_new_metadata_blocks(osb, 1, xattr_ac); | |
235 | + if (ret) { | |
236 | + mlog_errno(ret); | |
237 | + return ret; | |
238 | + } | |
239 | + *xattr_credits += OCFS2_XATTR_BLOCK_CREATE_CREDITS; | |
240 | + } | |
241 | + | |
242 | + if (dir->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE && | |
243 | + (s_size + a_size) > OCFS2_XATTR_FREE_IN_BLOCK(dir)) { | |
244 | + *want_clusters += 1; | |
245 | + *xattr_credits += ocfs2_blocks_per_xattr_bucket(dir->i_sb); | |
246 | + } | |
247 | + | |
248 | + /* reserve clusters for xattr value which will be set in B tree*/ | |
249 | + if (si->enable && si->value_len > OCFS2_XATTR_INLINE_SIZE) | |
250 | + *want_clusters += ocfs2_clusters_for_bytes(dir->i_sb, | |
251 | + si->value_len); | |
252 | + if (osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL && | |
253 | + acl_len > OCFS2_XATTR_INLINE_SIZE) { | |
254 | + *want_clusters += ocfs2_clusters_for_bytes(dir->i_sb, acl_len); | |
255 | + if (S_ISDIR(mode)) | |
256 | + *want_clusters += ocfs2_clusters_for_bytes(dir->i_sb, | |
257 | + acl_len); | |
258 | + } | |
259 | + | |
260 | + return ret; | |
261 | +} | |
262 | + | |
263 | static int ocfs2_xattr_extend_allocation(struct inode *inode, | |
264 | u32 clusters_to_add, | |
265 | struct buffer_head *xattr_bh, | |
266 | diff --git a/fs/ocfs2/xattr.h b/fs/ocfs2/xattr.h | |
267 | index 6163df3..9a67e7d 100644 | |
268 | --- a/fs/ocfs2/xattr.h | |
269 | +++ b/fs/ocfs2/xattr.h | |
270 | @@ -66,5 +66,8 @@ int ocfs2_init_security_set(handle_t *, struct inode *, | |
271 | int ocfs2_calc_security_init(struct inode *, | |
272 | struct ocfs2_security_xattr_info *, | |
273 | int *, int *, struct ocfs2_alloc_context **); | |
274 | +int ocfs2_calc_xattr_init(struct inode *, struct buffer_head *, | |
275 | + int, struct ocfs2_security_xattr_info *, | |
276 | + int *, int *, struct ocfs2_alloc_context **); | |
277 | ||
278 | #endif /* OCFS2_XATTR_H */ | |
279 | -- | |
280 | 1.5.6 | |
281 |