Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / os / filestore / chain_xattr.h
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"
8 #include <errno.h>
9 #include <stdio.h>
10 #include "common/xattr.h"
11 #include "include/assert.h"
12 #include "include/buffer_fwd.h"
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