Skip to content

Commit ae46578

Browse files
committed
afs: Get YFS ACLs and information through xattrs
The YFS/AuriStor variant of AFS provides more capable ACLs and provides per-volume ACLs and per-file ACLs as well as per-directory ACLs. It also provides some extra information that can be retrieved through four ACLs: (1) afs.yfs.acl The YFS file ACL (not the same format as afs.acl). (2) afs.yfs.vol_acl The YFS volume ACL. (3) afs.yfs.acl_inherited "1" if a file's ACL is inherited from its parent directory, "0" otherwise. (4) afs.yfs.acl_num_cleaned The number of of ACEs removed from the ACL by the server because the PT entries were removed from the PTS database (ie. the subject is no longer known). Signed-off-by: David Howells <dhowells@redhat.com>
1 parent b10494a commit ae46578

File tree

4 files changed

+304
-4
lines changed

4 files changed

+304
-4
lines changed

fs/afs/internal.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,6 +1371,19 @@ extern int yfs_fs_inline_bulk_status(struct afs_fs_cursor *, struct afs_net *,
13711371
struct afs_callback *, unsigned int,
13721372
struct afs_volsync *);
13731373

1374+
struct yfs_acl {
1375+
struct afs_acl *acl; /* Dir/file/symlink ACL */
1376+
struct afs_acl *vol_acl; /* Whole volume ACL */
1377+
u32 inherit_flag; /* True if ACL is inherited from parent dir */
1378+
u32 num_cleaned; /* Number of ACEs removed due to subject removal */
1379+
unsigned int flags;
1380+
#define YFS_ACL_WANT_ACL 0x01 /* Set if caller wants ->acl */
1381+
#define YFS_ACL_WANT_VOL_ACL 0x02 /* Set if caller wants ->vol_acl */
1382+
};
1383+
1384+
extern void yfs_free_opaque_acl(struct yfs_acl *);
1385+
extern struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *, unsigned int);
1386+
13741387
/*
13751388
* Miscellaneous inline functions.
13761389
*/

fs/afs/protocol_yfs.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ enum YFS_CM_Operations {
3131
};
3232

3333
enum YFS_FS_Operations {
34-
YFSFETCHACL = 64131, /* YFS Fetch file ACL */
34+
YFSFETCHACL = 64131, /* YFS Fetch file AFS3 ACL */
3535
YFSFETCHSTATUS = 64132, /* YFS Fetch file status */
36-
YFSSTOREACL = 64134, /* YFS Store file ACL */
36+
YFSSTOREACL = 64134, /* YFS Store file AFS3 ACL */
3737
YFSSTORESTATUS = 64135, /* YFS Store file status */
3838
YFSREMOVEFILE = 64136, /* YFS Remove a file */
3939
YFSCREATEFILE = 64137, /* YFS Create a file */
@@ -49,7 +49,7 @@ enum YFS_FS_Operations {
4949
YFSRELEASELOCK = 64158, /* YFS Release a file lock */
5050
YFSLOOKUP = 64161, /* YFS lookup file in directory */
5151
YFSFLUSHCPS = 64165,
52-
YFSFETCHOPAQUEACL = 64168,
52+
YFSFETCHOPAQUEACL = 64168, /* YFS Fetch file YFS ACL */
5353
YFSWHOAMI = 64170,
5454
YFSREMOVEACL = 64171,
5555
YFSREMOVEFILE2 = 64173,

fs/afs/xattr.c

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ static const char afs_xattr_list[] =
1919
"afs.acl\0"
2020
"afs.cell\0"
2121
"afs.fid\0"
22-
"afs.volume";
22+
"afs.volume\0"
23+
"afs.yfs.acl\0"
24+
"afs.yfs.acl_inherited\0"
25+
"afs.yfs.acl_num_cleaned\0"
26+
"afs.yfs.vol_acl";
2327

2428
/*
2529
* Retrieve a list of the supported xattrs.
@@ -133,6 +137,100 @@ static const struct xattr_handler afs_xattr_afs_acl_handler = {
133137
.set = afs_xattr_set_acl,
134138
};
135139

140+
/*
141+
* Get a file's YFS ACL.
142+
*/
143+
static int afs_xattr_get_yfs(const struct xattr_handler *handler,
144+
struct dentry *dentry,
145+
struct inode *inode, const char *name,
146+
void *buffer, size_t size)
147+
{
148+
struct afs_fs_cursor fc;
149+
struct afs_vnode *vnode = AFS_FS_I(inode);
150+
struct yfs_acl *yacl = NULL;
151+
struct key *key;
152+
unsigned int flags = 0;
153+
char buf[16], *data;
154+
int which = 0, dsize, ret;
155+
156+
if (strcmp(name, "acl") == 0)
157+
which = 0;
158+
else if (strcmp(name, "acl_inherited") == 0)
159+
which = 1;
160+
else if (strcmp(name, "acl_num_cleaned") == 0)
161+
which = 2;
162+
else if (strcmp(name, "vol_acl") == 0)
163+
which = 3;
164+
else
165+
return -EOPNOTSUPP;
166+
167+
if (which == 0)
168+
flags |= YFS_ACL_WANT_ACL;
169+
else if (which == 3)
170+
flags |= YFS_ACL_WANT_VOL_ACL;
171+
172+
key = afs_request_key(vnode->volume->cell);
173+
if (IS_ERR(key))
174+
return PTR_ERR(key);
175+
176+
ret = -ERESTARTSYS;
177+
if (afs_begin_vnode_operation(&fc, vnode, key)) {
178+
while (afs_select_fileserver(&fc)) {
179+
fc.cb_break = afs_calc_vnode_cb_break(vnode);
180+
yacl = yfs_fs_fetch_opaque_acl(&fc, flags);
181+
}
182+
183+
afs_check_for_remote_deletion(&fc, fc.vnode);
184+
afs_vnode_commit_status(&fc, vnode, fc.cb_break);
185+
ret = afs_end_vnode_operation(&fc);
186+
}
187+
188+
if (ret == 0) {
189+
switch (which) {
190+
case 0:
191+
data = yacl->acl->data;
192+
dsize = yacl->acl->size;
193+
break;
194+
case 1:
195+
data = buf;
196+
dsize = snprintf(buf, sizeof(buf), "%u",
197+
yacl->inherit_flag);
198+
break;
199+
case 2:
200+
data = buf;
201+
dsize = snprintf(buf, sizeof(buf), "%u",
202+
yacl->num_cleaned);
203+
break;
204+
case 3:
205+
data = yacl->vol_acl->data;
206+
dsize = yacl->vol_acl->size;
207+
break;
208+
default:
209+
ret = -EOPNOTSUPP;
210+
goto out;
211+
}
212+
213+
ret = dsize;
214+
if (size > 0) {
215+
if (dsize > size) {
216+
ret = -ERANGE;
217+
goto out;
218+
}
219+
memcpy(buffer, data, dsize);
220+
}
221+
}
222+
223+
out:
224+
yfs_free_opaque_acl(yacl);
225+
key_put(key);
226+
return ret;
227+
}
228+
229+
static const struct xattr_handler afs_xattr_yfs_handler = {
230+
.prefix = "afs.yfs.",
231+
.get = afs_xattr_get_yfs,
232+
};
233+
136234
/*
137235
* Get the name of the cell on which a file resides.
138236
*/
@@ -227,5 +325,6 @@ const struct xattr_handler *afs_xattr_handlers[] = {
227325
&afs_xattr_afs_cell_handler,
228326
&afs_xattr_afs_fid_handler,
229327
&afs_xattr_afs_volume_handler,
328+
&afs_xattr_yfs_handler, /* afs.yfs. prefix */
230329
NULL
231330
};

fs/afs/yfsclient.c

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2204,3 +2204,191 @@ int yfs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
22042204
afs_make_call(&fc->ac, call, GFP_NOFS);
22052205
return afs_wait_for_call_to_complete(call, &fc->ac);
22062206
}
2207+
2208+
/*
2209+
* Deliver reply data to an YFS.FetchOpaqueACL.
2210+
*/
2211+
static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)
2212+
{
2213+
struct afs_volsync *volsync = call->reply[2];
2214+
struct afs_vnode *vnode = call->reply[1];
2215+
struct yfs_acl *yacl = call->reply[0];
2216+
struct afs_acl *acl;
2217+
const __be32 *bp;
2218+
unsigned int size;
2219+
int ret;
2220+
2221+
_enter("{%u}", call->unmarshall);
2222+
2223+
switch (call->unmarshall) {
2224+
case 0:
2225+
afs_extract_to_tmp(call);
2226+
call->unmarshall++;
2227+
2228+
/* Extract the file ACL length */
2229+
case 1:
2230+
ret = afs_extract_data(call, true);
2231+
if (ret < 0)
2232+
return ret;
2233+
2234+
size = call->count2 = ntohl(call->tmp);
2235+
size = round_up(size, 4);
2236+
2237+
if (yacl->flags & YFS_ACL_WANT_ACL) {
2238+
acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL);
2239+
if (!acl)
2240+
return -ENOMEM;
2241+
yacl->acl = acl;
2242+
acl->size = call->count2;
2243+
afs_extract_begin(call, acl->data, size);
2244+
} else {
2245+
iov_iter_discard(&call->iter, READ, size);
2246+
}
2247+
call->unmarshall++;
2248+
2249+
/* Extract the file ACL */
2250+
case 2:
2251+
ret = afs_extract_data(call, true);
2252+
if (ret < 0)
2253+
return ret;
2254+
2255+
afs_extract_to_tmp(call);
2256+
call->unmarshall++;
2257+
2258+
/* Extract the volume ACL length */
2259+
case 3:
2260+
ret = afs_extract_data(call, true);
2261+
if (ret < 0)
2262+
return ret;
2263+
2264+
size = call->count2 = ntohl(call->tmp);
2265+
size = round_up(size, 4);
2266+
2267+
if (yacl->flags & YFS_ACL_WANT_VOL_ACL) {
2268+
acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL);
2269+
if (!acl)
2270+
return -ENOMEM;
2271+
yacl->vol_acl = acl;
2272+
acl->size = call->count2;
2273+
afs_extract_begin(call, acl->data, size);
2274+
} else {
2275+
iov_iter_discard(&call->iter, READ, size);
2276+
}
2277+
call->unmarshall++;
2278+
2279+
/* Extract the volume ACL */
2280+
case 4:
2281+
ret = afs_extract_data(call, true);
2282+
if (ret < 0)
2283+
return ret;
2284+
2285+
afs_extract_to_buf(call,
2286+
sizeof(__be32) * 2 +
2287+
sizeof(struct yfs_xdr_YFSFetchStatus) +
2288+
sizeof(struct yfs_xdr_YFSVolSync));
2289+
call->unmarshall++;
2290+
2291+
/* extract the metadata */
2292+
case 5:
2293+
ret = afs_extract_data(call, false);
2294+
if (ret < 0)
2295+
return ret;
2296+
2297+
bp = call->buffer;
2298+
yacl->inherit_flag = ntohl(*bp++);
2299+
yacl->num_cleaned = ntohl(*bp++);
2300+
ret = yfs_decode_status(call, &bp, &vnode->status, vnode,
2301+
&call->expected_version, NULL);
2302+
if (ret < 0)
2303+
return ret;
2304+
xdr_decode_YFSVolSync(&bp, volsync);
2305+
2306+
call->unmarshall++;
2307+
2308+
case 6:
2309+
break;
2310+
}
2311+
2312+
_leave(" = 0 [done]");
2313+
return 0;
2314+
}
2315+
2316+
void yfs_free_opaque_acl(struct yfs_acl *yacl)
2317+
{
2318+
if (yacl) {
2319+
kfree(yacl->acl);
2320+
kfree(yacl->vol_acl);
2321+
kfree(yacl);
2322+
}
2323+
}
2324+
2325+
static void yfs_destroy_fs_fetch_opaque_acl(struct afs_call *call)
2326+
{
2327+
yfs_free_opaque_acl(call->reply[0]);
2328+
afs_flat_call_destructor(call);
2329+
}
2330+
2331+
/*
2332+
* YFS.FetchOpaqueACL operation type
2333+
*/
2334+
static const struct afs_call_type yfs_RXYFSFetchOpaqueACL = {
2335+
.name = "YFS.FetchOpaqueACL",
2336+
.op = yfs_FS_FetchOpaqueACL,
2337+
.deliver = yfs_deliver_fs_fetch_opaque_acl,
2338+
.destructor = yfs_destroy_fs_fetch_opaque_acl,
2339+
};
2340+
2341+
/*
2342+
* Fetch the YFS advanced ACLs for a file.
2343+
*/
2344+
struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *fc,
2345+
unsigned int flags)
2346+
{
2347+
struct afs_vnode *vnode = fc->vnode;
2348+
struct afs_call *call;
2349+
struct yfs_acl *yacl;
2350+
struct afs_net *net = afs_v2net(vnode);
2351+
__be32 *bp;
2352+
2353+
_enter(",%x,{%llx:%llu},,",
2354+
key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
2355+
2356+
call = afs_alloc_flat_call(net, &yfs_RXYFSFetchOpaqueACL,
2357+
sizeof(__be32) * 2 +
2358+
sizeof(struct yfs_xdr_YFSFid),
2359+
sizeof(__be32) * 2 +
2360+
sizeof(struct yfs_xdr_YFSFetchStatus) +
2361+
sizeof(struct yfs_xdr_YFSVolSync));
2362+
if (!call)
2363+
goto nomem;
2364+
2365+
yacl = kzalloc(sizeof(struct yfs_acl), GFP_KERNEL);
2366+
if (!yacl)
2367+
goto nomem_call;
2368+
2369+
yacl->flags = flags;
2370+
call->key = fc->key;
2371+
call->reply[0] = yacl;
2372+
call->reply[1] = vnode;
2373+
call->reply[2] = NULL; /* volsync */
2374+
call->ret_reply0 = true;
2375+
2376+
/* marshall the parameters */
2377+
bp = call->request;
2378+
bp = xdr_encode_u32(bp, YFSFETCHOPAQUEACL);
2379+
bp = xdr_encode_u32(bp, 0); /* RPC flags */
2380+
bp = xdr_encode_YFSFid(bp, &vnode->fid);
2381+
yfs_check_req(call, bp);
2382+
2383+
call->cb_break = fc->cb_break;
2384+
afs_use_fs_server(call, fc->cbi);
2385+
trace_afs_make_fs_call(call, &vnode->fid);
2386+
afs_make_call(&fc->ac, call, GFP_KERNEL);
2387+
return (struct yfs_acl *)afs_wait_for_call_to_complete(call, &fc->ac);
2388+
2389+
nomem_call:
2390+
afs_put_call(call);
2391+
nomem:
2392+
fc->ac.error = -ENOMEM;
2393+
return ERR_PTR(-ENOMEM);
2394+
}

0 commit comments

Comments
 (0)