]> git.proxmox.com Git - ceph.git/blame - ceph/src/os/filestore/chain_xattr.h
update sources to v12.1.0
[ceph.git] / ceph / src / os / filestore / chain_xattr.h
CommitLineData
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
35static 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}
40static 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
46static 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}
51static 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
57static 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}
62static 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
68static 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}
73static 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
82int chain_getxattr(const char *fn, const char *name, void *val, size_t size);
83int chain_getxattr_buf(const char *fn, const char *name, bufferptr *bp);
84int chain_fgetxattr(int fd, const char *name, void *val, size_t size);
85
86int get_xattr_block_size(size_t size);
87void get_raw_xattr_name(const char *name, int i, char *raw_name, int raw_len);
88
89template <bool skip_chain_cleanup=false, bool ensure_single_attr=false>
90int 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
133template <bool skip_chain_cleanup=false, bool ensure_single_attr=false>
134int 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
177int chain_listxattr(const char *fn, char *names, size_t len);
178int chain_flistxattr(int fd, char *names, size_t len);
179int chain_removexattr(const char *fn, const char *name);
180int chain_fremovexattr(int fd, const char *name);
181
182#endif