aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ocfs2/namei.c107
-rw-r--r--fs/ocfs2/xattr.c70
-rw-r--r--fs/ocfs2/xattr.h17
3 files changed, 182 insertions, 12 deletions
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index e8ff0bae179d..40da46b907fb 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -229,6 +229,12 @@ static int ocfs2_mknod(struct inode *dir,
229 struct inode *inode = NULL; 229 struct inode *inode = NULL;
230 struct ocfs2_alloc_context *inode_ac = NULL; 230 struct ocfs2_alloc_context *inode_ac = NULL;
231 struct ocfs2_alloc_context *data_ac = NULL; 231 struct ocfs2_alloc_context *data_ac = NULL;
232 struct ocfs2_alloc_context *xattr_ac = NULL;
233 int want_clusters = 0;
234 int xattr_credits = 0;
235 struct ocfs2_security_xattr_info si = {
236 .enable = 1,
237 };
232 238
233 mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode, 239 mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode,
234 (unsigned long)dev, dentry->d_name.len, 240 (unsigned long)dev, dentry->d_name.len,
@@ -285,17 +291,39 @@ static int ocfs2_mknod(struct inode *dir,
285 goto leave; 291 goto leave;
286 } 292 }
287 293
288 /* Reserve a cluster if creating an extent based directory. */ 294 /* get security xattr */
289 if (S_ISDIR(mode) && !ocfs2_supports_inline_data(osb)) { 295 status = ocfs2_init_security_get(inode, dir, &si);
290 status = ocfs2_reserve_clusters(osb, 1, &data_ac); 296 if (status) {
297 if (status == -EOPNOTSUPP)
298 si.enable = 0;
299 else {
300 mlog_errno(status);
301 goto leave;
302 }
303 }
304
305 /* calculate meta data/clusters for setting security xattr */
306 if (si.enable) {
307 status = ocfs2_calc_security_init(dir, &si, &want_clusters,
308 &xattr_credits, &xattr_ac);
291 if (status < 0) { 309 if (status < 0) {
292 if (status != -ENOSPC) 310 mlog_errno(status);
293 mlog_errno(status);
294 goto leave; 311 goto leave;
295 } 312 }
296 } 313 }
297 314
298 handle = ocfs2_start_trans(osb, OCFS2_MKNOD_CREDITS); 315 /* Reserve a cluster if creating an extent based directory. */
316 if (S_ISDIR(mode) && !ocfs2_supports_inline_data(osb))
317 want_clusters += 1;
318
319 status = ocfs2_reserve_clusters(osb, want_clusters, &data_ac);
320 if (status < 0) {
321 if (status != -ENOSPC)
322 mlog_errno(status);
323 goto leave;
324 }
325
326 handle = ocfs2_start_trans(osb, OCFS2_MKNOD_CREDITS + xattr_credits);
299 if (IS_ERR(handle)) { 327 if (IS_ERR(handle)) {
300 status = PTR_ERR(handle); 328 status = PTR_ERR(handle);
301 handle = NULL; 329 handle = NULL;
@@ -335,6 +363,15 @@ static int ocfs2_mknod(struct inode *dir,
335 inc_nlink(dir); 363 inc_nlink(dir);
336 } 364 }
337 365
366 if (si.enable) {
367 status = ocfs2_init_security_set(handle, inode, new_fe_bh, &si,
368 xattr_ac, data_ac);
369 if (status < 0) {
370 mlog_errno(status);
371 goto leave;
372 }
373 }
374
338 status = ocfs2_add_entry(handle, dentry, inode, 375 status = ocfs2_add_entry(handle, dentry, inode,
339 OCFS2_I(inode)->ip_blkno, parent_fe_bh, 376 OCFS2_I(inode)->ip_blkno, parent_fe_bh,
340 de_bh); 377 de_bh);
@@ -366,6 +403,8 @@ leave:
366 brelse(new_fe_bh); 403 brelse(new_fe_bh);
367 brelse(de_bh); 404 brelse(de_bh);
368 brelse(parent_fe_bh); 405 brelse(parent_fe_bh);
406 kfree(si.name);
407 kfree(si.value);
369 408
370 if ((status < 0) && inode) { 409 if ((status < 0) && inode) {
371 clear_nlink(inode); 410 clear_nlink(inode);
@@ -378,6 +417,9 @@ leave:
378 if (data_ac) 417 if (data_ac)
379 ocfs2_free_alloc_context(data_ac); 418 ocfs2_free_alloc_context(data_ac);
380 419
420 if (xattr_ac)
421 ocfs2_free_alloc_context(xattr_ac);
422
381 mlog_exit(status); 423 mlog_exit(status);
382 424
383 return status; 425 return status;
@@ -1508,6 +1550,12 @@ static int ocfs2_symlink(struct inode *dir,
1508 handle_t *handle = NULL; 1550 handle_t *handle = NULL;
1509 struct ocfs2_alloc_context *inode_ac = NULL; 1551 struct ocfs2_alloc_context *inode_ac = NULL;
1510 struct ocfs2_alloc_context *data_ac = NULL; 1552 struct ocfs2_alloc_context *data_ac = NULL;
1553 struct ocfs2_alloc_context *xattr_ac = NULL;
1554 int want_clusters = 0;
1555 int xattr_credits = 0;
1556 struct ocfs2_security_xattr_info si = {
1557 .enable = 1,
1558 };
1511 1559
1512 mlog_entry("(0x%p, 0x%p, symname='%s' actual='%.*s')\n", dir, 1560 mlog_entry("(0x%p, 0x%p, symname='%s' actual='%.*s')\n", dir,
1513 dentry, symname, dentry->d_name.len, dentry->d_name.name); 1561 dentry, symname, dentry->d_name.len, dentry->d_name.name);
@@ -1561,17 +1609,39 @@ static int ocfs2_symlink(struct inode *dir,
1561 goto bail; 1609 goto bail;
1562 } 1610 }
1563 1611
1564 /* don't reserve bitmap space for fast symlinks. */ 1612 /* get security xattr */
1565 if (l > ocfs2_fast_symlink_chars(sb)) { 1613 status = ocfs2_init_security_get(inode, dir, &si);
1566 status = ocfs2_reserve_clusters(osb, 1, &data_ac); 1614 if (status) {
1615 if (status == -EOPNOTSUPP)
1616 si.enable = 0;
1617 else {
1618 mlog_errno(status);
1619 goto bail;
1620 }
1621 }
1622
1623 /* calculate meta data/clusters for setting security xattr */
1624 if (si.enable) {
1625 status = ocfs2_calc_security_init(dir, &si, &want_clusters,
1626 &xattr_credits, &xattr_ac);
1567 if (status < 0) { 1627 if (status < 0) {
1568 if (status != -ENOSPC) 1628 mlog_errno(status);
1569 mlog_errno(status);
1570 goto bail; 1629 goto bail;
1571 } 1630 }
1572 } 1631 }
1573 1632
1574 handle = ocfs2_start_trans(osb, credits); 1633 /* don't reserve bitmap space for fast symlinks. */
1634 if (l > ocfs2_fast_symlink_chars(sb))
1635 want_clusters += 1;
1636
1637 status = ocfs2_reserve_clusters(osb, want_clusters, &data_ac);
1638 if (status < 0) {
1639 if (status != -ENOSPC)
1640 mlog_errno(status);
1641 goto bail;
1642 }
1643
1644 handle = ocfs2_start_trans(osb, credits + xattr_credits);
1575 if (IS_ERR(handle)) { 1645 if (IS_ERR(handle)) {
1576 status = PTR_ERR(handle); 1646 status = PTR_ERR(handle);
1577 handle = NULL; 1647 handle = NULL;
@@ -1632,6 +1702,15 @@ static int ocfs2_symlink(struct inode *dir,
1632 } 1702 }
1633 } 1703 }
1634 1704
1705 if (si.enable) {
1706 status = ocfs2_init_security_set(handle, inode, new_fe_bh, &si,
1707 xattr_ac, data_ac);
1708 if (status < 0) {
1709 mlog_errno(status);
1710 goto bail;
1711 }
1712 }
1713
1635 status = ocfs2_add_entry(handle, dentry, inode, 1714 status = ocfs2_add_entry(handle, dentry, inode,
1636 le64_to_cpu(fe->i_blkno), parent_fe_bh, 1715 le64_to_cpu(fe->i_blkno), parent_fe_bh,
1637 de_bh); 1716 de_bh);
@@ -1658,10 +1737,14 @@ bail:
1658 brelse(new_fe_bh); 1737 brelse(new_fe_bh);
1659 brelse(parent_fe_bh); 1738 brelse(parent_fe_bh);
1660 brelse(de_bh); 1739 brelse(de_bh);
1740 kfree(si.name);
1741 kfree(si.value);
1661 if (inode_ac) 1742 if (inode_ac)
1662 ocfs2_free_alloc_context(inode_ac); 1743 ocfs2_free_alloc_context(inode_ac);
1663 if (data_ac) 1744 if (data_ac)
1664 ocfs2_free_alloc_context(data_ac); 1745 ocfs2_free_alloc_context(data_ac);
1746 if (xattr_ac)
1747 ocfs2_free_alloc_context(xattr_ac);
1665 if ((status < 0) && inode) { 1748 if ((status < 0) && inode) {
1666 clear_nlink(inode); 1749 clear_nlink(inode);
1667 iput(inode); 1750 iput(inode);
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index db03162914cc..2cab0d6615f9 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -81,6 +81,9 @@ struct ocfs2_xattr_set_ctxt {
81 81
82#define OCFS2_XATTR_ROOT_SIZE (sizeof(struct ocfs2_xattr_def_value_root)) 82#define OCFS2_XATTR_ROOT_SIZE (sizeof(struct ocfs2_xattr_def_value_root))
83#define OCFS2_XATTR_INLINE_SIZE 80 83#define OCFS2_XATTR_INLINE_SIZE 80
84#define OCFS2_XATTR_FREE_IN_IBODY (OCFS2_MIN_XATTR_INLINE_SIZE \
85 - sizeof(struct ocfs2_xattr_header) \
86 - sizeof(__u32))
84 87
85static struct ocfs2_xattr_def_value_root def_xv = { 88static struct ocfs2_xattr_def_value_root def_xv = {
86 .xv.xr_list.l_count = cpu_to_le16(1), 89 .xv.xr_list.l_count = cpu_to_le16(1),
@@ -343,6 +346,52 @@ static void ocfs2_xattr_hash_entry(struct inode *inode,
343 return; 346 return;
344} 347}
345 348
349static int ocfs2_xattr_entry_real_size(int name_len, size_t value_len)
350{
351 int size = 0;
352
353 if (value_len <= OCFS2_XATTR_INLINE_SIZE)
354 size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_SIZE(value_len);
355 else
356 size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE;
357 size += sizeof(struct ocfs2_xattr_entry);
358
359 return size;
360}
361
362int ocfs2_calc_security_init(struct inode *dir,
363 struct ocfs2_security_xattr_info *si,
364 int *want_clusters,
365 int *xattr_credits,
366 struct ocfs2_alloc_context **xattr_ac)
367{
368 int ret = 0;
369 struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
370 int s_size = ocfs2_xattr_entry_real_size(strlen(si->name),
371 si->value_len);
372
373 /*
374 * The max space of security xattr taken inline is
375 * 256(name) + 80(value) + 16(entry) = 352 bytes,
376 * So reserve one metadata block for it is ok.
377 */
378 if (dir->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE ||
379 s_size > OCFS2_XATTR_FREE_IN_IBODY) {
380 ret = ocfs2_reserve_new_metadata_blocks(osb, 1, xattr_ac);
381 if (ret) {
382 mlog_errno(ret);
383 return ret;
384 }
385 *xattr_credits += OCFS2_XATTR_BLOCK_CREATE_CREDITS;
386 }
387
388 /* reserve clusters for xattr value which will be set in B tree*/
389 if (si->value_len > OCFS2_XATTR_INLINE_SIZE)
390 *want_clusters += ocfs2_clusters_for_bytes(dir->i_sb,
391 si->value_len);
392 return ret;
393}
394
346static int ocfs2_xattr_extend_allocation(struct inode *inode, 395static int ocfs2_xattr_extend_allocation(struct inode *inode,
347 u32 clusters_to_add, 396 u32 clusters_to_add,
348 struct buffer_head *xattr_bh, 397 struct buffer_head *xattr_bh,
@@ -5016,6 +5065,27 @@ static int ocfs2_xattr_security_set(struct inode *inode, const char *name,
5016 size, flags); 5065 size, flags);
5017} 5066}
5018 5067
5068int ocfs2_init_security_get(struct inode *inode,
5069 struct inode *dir,
5070 struct ocfs2_security_xattr_info *si)
5071{
5072 return security_inode_init_security(inode, dir, &si->name, &si->value,
5073 &si->value_len);
5074}
5075
5076int ocfs2_init_security_set(handle_t *handle,
5077 struct inode *inode,
5078 struct buffer_head *di_bh,
5079 struct ocfs2_security_xattr_info *si,
5080 struct ocfs2_alloc_context *xattr_ac,
5081 struct ocfs2_alloc_context *data_ac)
5082{
5083 return ocfs2_xattr_set_handle(handle, inode, di_bh,
5084 OCFS2_XATTR_INDEX_SECURITY,
5085 si->name, si->value, si->value_len, 0,
5086 xattr_ac, data_ac);
5087}
5088
5019struct xattr_handler ocfs2_xattr_security_handler = { 5089struct xattr_handler ocfs2_xattr_security_handler = {
5020 .prefix = XATTR_SECURITY_PREFIX, 5090 .prefix = XATTR_SECURITY_PREFIX,
5021 .list = ocfs2_xattr_security_list, 5091 .list = ocfs2_xattr_security_list,
diff --git a/fs/ocfs2/xattr.h b/fs/ocfs2/xattr.h
index 55c5256ff563..188ef6ba6836 100644
--- a/fs/ocfs2/xattr.h
+++ b/fs/ocfs2/xattr.h
@@ -30,6 +30,13 @@ enum ocfs2_xattr_type {
30 OCFS2_XATTR_MAX 30 OCFS2_XATTR_MAX
31}; 31};
32 32
33struct ocfs2_security_xattr_info {
34 int enable;
35 char *name;
36 void *value;
37 size_t value_len;
38};
39
33extern struct xattr_handler ocfs2_xattr_user_handler; 40extern struct xattr_handler ocfs2_xattr_user_handler;
34extern struct xattr_handler ocfs2_xattr_trusted_handler; 41extern struct xattr_handler ocfs2_xattr_trusted_handler;
35extern struct xattr_handler ocfs2_xattr_security_handler; 42extern struct xattr_handler ocfs2_xattr_security_handler;
@@ -43,5 +50,15 @@ int ocfs2_xattr_set_handle(handle_t *, struct inode *, struct buffer_head *,
43 struct ocfs2_alloc_context *, 50 struct ocfs2_alloc_context *,
44 struct ocfs2_alloc_context *); 51 struct ocfs2_alloc_context *);
45int ocfs2_xattr_remove(struct inode *, struct buffer_head *); 52int ocfs2_xattr_remove(struct inode *, struct buffer_head *);
53int ocfs2_init_security_get(struct inode *, struct inode *,
54 struct ocfs2_security_xattr_info *);
55int ocfs2_init_security_set(handle_t *, struct inode *,
56 struct buffer_head *,
57 struct ocfs2_security_xattr_info *,
58 struct ocfs2_alloc_context *,
59 struct ocfs2_alloc_context *);
60int ocfs2_calc_security_init(struct inode *,
61 struct ocfs2_security_xattr_info *,
62 int *, int *, struct ocfs2_alloc_context **);
46 63
47#endif /* OCFS2_XATTR_H */ 64#endif /* OCFS2_XATTR_H */