]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #ifndef __CEPH_OSD_CHAIN_XATTR_H | |
5 | #define __CEPH_OSD_CHAIN_XATTR_H | |
6 | ||
7 | #include "include/compat.h" | |
31f18b77 FG |
8 | #include <errno.h> |
9 | #include <stdio.h> | |
7c673cae FG |
10 | #include "common/xattr.h" |
11 | #include "include/assert.h" | |
31f18b77 | 12 | #include "include/buffer_fwd.h" |
7c673cae FG |
13 | |
14 | #if defined(__linux__) | |
15 | #include <linux/limits.h> | |
16 | #define CHAIN_XATTR_MAX_NAME_LEN ((XATTR_NAME_MAX + 1) / 2) | |
17 | #elif defined(__APPLE__) | |
18 | #include <sys/xattr.h> | |
19 | #define CHAIN_XATTR_MAX_NAME_LEN ((XATTR_MAXNAMELEN + 1) / 2) | |
20 | #else | |
21 | #define CHAIN_XATTR_MAX_NAME_LEN 128 | |
22 | #endif | |
23 | ||
24 | #define CHAIN_XATTR_MAX_BLOCK_LEN 2048 | |
25 | ||
26 | /* | |
27 | * XFS will only inline xattrs < 255 bytes, so for xattrs that are | |
28 | * likely to fit in the inode, stripe over short xattrs. | |
29 | */ | |
30 | #define CHAIN_XATTR_SHORT_BLOCK_LEN 250 | |
31 | #define CHAIN_XATTR_SHORT_LEN_THRESHOLD 1000 | |
32 | ||
33 | // wrappers to hide annoying errno handling. | |
34 | ||
35 | static inline int sys_fgetxattr(int fd, const char *name, void *val, size_t size) | |
36 | { | |
37 | int r = ::ceph_os_fgetxattr(fd, name, val, size); | |
38 | return (r < 0 ? -errno : r); | |
39 | } | |
40 | static inline int sys_getxattr(const char *fn, const char *name, void *val, size_t size) | |
41 | { | |
42 | int r = ::ceph_os_getxattr(fn, name, val, size); | |
43 | return (r < 0 ? -errno : r); | |
44 | } | |
45 | ||
46 | static inline int sys_setxattr(const char *fn, const char *name, const void *val, size_t size) | |
47 | { | |
48 | int r = ::ceph_os_setxattr(fn, name, val, size); | |
49 | return (r < 0 ? -errno : r); | |
50 | } | |
51 | static inline int sys_fsetxattr(int fd, const char *name, const void *val, size_t size) | |
52 | { | |
53 | int r = ::ceph_os_fsetxattr(fd, name, val, size); | |
54 | return (r < 0 ? -errno : r); | |
55 | } | |
56 | ||
57 | static inline int sys_listxattr(const char *fn, char *names, size_t len) | |
58 | { | |
59 | int r = ::ceph_os_listxattr(fn, names, len); | |
60 | return (r < 0 ? -errno : r); | |
61 | } | |
62 | static inline int sys_flistxattr(int fd, char *names, size_t len) | |
63 | { | |
64 | int r = ::ceph_os_flistxattr(fd, names, len); | |
65 | return (r < 0 ? -errno : r); | |
66 | } | |
67 | ||
68 | static inline int sys_removexattr(const char *fn, const char *name) | |
69 | { | |
70 | int r = ::ceph_os_removexattr(fn, name); | |
71 | return (r < 0 ? -errno : r); | |
72 | } | |
73 | static inline int sys_fremovexattr(int fd, const char *name) | |
74 | { | |
75 | int r = ::ceph_os_fremovexattr(fd, name); | |
76 | return (r < 0 ? -errno : r); | |
77 | } | |
78 | ||
79 | ||
80 | // wrappers to chain large values across multiple xattrs | |
81 | ||
82 | int chain_getxattr(const char *fn, const char *name, void *val, size_t size); | |
83 | int chain_getxattr_buf(const char *fn, const char *name, bufferptr *bp); | |
84 | int chain_fgetxattr(int fd, const char *name, void *val, size_t size); | |
85 | ||
86 | int get_xattr_block_size(size_t size); | |
87 | void get_raw_xattr_name(const char *name, int i, char *raw_name, int raw_len); | |
88 | ||
89 | template <bool skip_chain_cleanup=false, bool ensure_single_attr=false> | |
90 | int chain_setxattr( | |
91 | const char *fn, const char *name, const void *val, size_t size) | |
92 | { | |
93 | int i = 0, pos = 0; | |
94 | char raw_name[CHAIN_XATTR_MAX_NAME_LEN * 2 + 16]; | |
95 | int ret = 0; | |
96 | size_t max_chunk_size = | |
97 | ensure_single_attr ? size : get_xattr_block_size(size); | |
98 | ||
99 | static_assert( | |
100 | !skip_chain_cleanup || ensure_single_attr, | |
101 | "skip_chain_cleanup must imply ensure_single_attr"); | |
102 | ||
103 | do { | |
104 | size_t chunk_size = (size < max_chunk_size ? size : max_chunk_size); | |
105 | get_raw_xattr_name(name, i, raw_name, sizeof(raw_name)); | |
106 | size -= chunk_size; | |
107 | ||
108 | int r = sys_setxattr(fn, raw_name, (char *)val + pos, chunk_size); | |
109 | if (r < 0) { | |
110 | ret = r; | |
111 | break; | |
112 | } | |
113 | pos += chunk_size; | |
114 | ret = pos; | |
115 | i++; | |
116 | assert(size == 0 || !ensure_single_attr); | |
117 | } while (size); | |
118 | ||
119 | if (ret >= 0 && !skip_chain_cleanup) { | |
120 | int r; | |
121 | do { | |
122 | get_raw_xattr_name(name, i, raw_name, sizeof(raw_name)); | |
123 | r = sys_removexattr(fn, raw_name); | |
124 | if (r < 0 && r != -ENODATA) | |
125 | ret = r; | |
126 | i++; | |
127 | } while (r != -ENODATA); | |
128 | } | |
129 | ||
130 | return ret; | |
131 | } | |
132 | ||
133 | template <bool skip_chain_cleanup=false, bool ensure_single_attr=false> | |
134 | int chain_fsetxattr( | |
135 | int fd, const char *name, const void *val, size_t size) | |
136 | { | |
137 | int i = 0, pos = 0; | |
138 | char raw_name[CHAIN_XATTR_MAX_NAME_LEN * 2 + 16]; | |
139 | int ret = 0; | |
140 | size_t max_chunk_size = | |
141 | ensure_single_attr ? size : get_xattr_block_size(size); | |
142 | ||
143 | static_assert( | |
144 | !skip_chain_cleanup || ensure_single_attr, | |
145 | "skip_chain_cleanup must imply ensure_single_attr"); | |
146 | ||
147 | do { | |
148 | size_t chunk_size = (size < max_chunk_size ? size : max_chunk_size); | |
149 | get_raw_xattr_name(name, i, raw_name, sizeof(raw_name)); | |
150 | size -= chunk_size; | |
151 | ||
152 | int r = sys_fsetxattr(fd, raw_name, (char *)val + pos, chunk_size); | |
153 | if (r < 0) { | |
154 | ret = r; | |
155 | break; | |
156 | } | |
157 | pos += chunk_size; | |
158 | ret = pos; | |
159 | i++; | |
160 | assert(size == 0 || !ensure_single_attr); | |
161 | } while (size); | |
162 | ||
163 | if (ret >= 0 && !skip_chain_cleanup) { | |
164 | int r; | |
165 | do { | |
166 | get_raw_xattr_name(name, i, raw_name, sizeof(raw_name)); | |
167 | r = sys_fremovexattr(fd, raw_name); | |
168 | if (r < 0 && r != -ENODATA) | |
169 | ret = r; | |
170 | i++; | |
171 | } while (r != -ENODATA); | |
172 | } | |
173 | ||
174 | return ret; | |
175 | } | |
176 | ||
177 | int chain_listxattr(const char *fn, char *names, size_t len); | |
178 | int chain_flistxattr(int fd, char *names, size_t len); | |
179 | int chain_removexattr(const char *fn, const char *name); | |
180 | int chain_fremovexattr(int fd, const char *name); | |
181 | ||
182 | #endif |