Skip to content

Commit ffe8087

Browse files
soumyakodurinixpanic
authored andcommitted
Upcall: Read gfid from iatt in case of invalid inode
When any file/dir is looked upon for the first time, inode created shall be invalid till it gets linked to the inode table. In such cases, read the gfid from the iatt structure returned as part of such fops for UPCALL processing. Change-Id: Ie5eb2f3be18c34cf7ef172e126c9db5ef7a8512b BUG: 1283983 Signed-off-by: Soumya Koduri <[email protected]> Reviewed-on: http://review.gluster.org/12773 Reviewed-by: Kaleb KEITHLEY <[email protected]> Tested-by: NetBSD Build System <[email protected]> Tested-by: Gluster Build System <[email protected]> Reviewed-by: Niels de Vos <[email protected]>
1 parent f2c52ae commit ffe8087

File tree

6 files changed

+198
-22
lines changed

6 files changed

+198
-22
lines changed

api/src/glfs-handleops.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,6 +1288,10 @@ pub_glfs_h_create_from_handle (struct glfs *fs, unsigned char *handle, int len,
12881288

12891289
memcpy (loc.gfid, handle, GFAPI_HANDLE_LENGTH);
12901290

1291+
/* make sure the gfid received is valid */
1292+
GF_VALIDATE_OR_GOTO ("glfs_h_create_from_handle",
1293+
!(gf_uuid_is_null (loc.gfid)), out);
1294+
12911295
newinode = inode_find (subvol->itable, loc.gfid);
12921296
if (newinode) {
12931297
if (!stat) /* No need of lookup */

tests/basic/gfapi/bug1283983.c

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#include <fcntl.h>
2+
#include <unistd.h>
3+
#include <time.h>
4+
#include <limits.h>
5+
#include <alloca.h>
6+
#include <string.h>
7+
#include <stdio.h>
8+
#include <errno.h>
9+
#include <stdlib.h>
10+
#include <glusterfs/api/glfs.h>
11+
#include <glusterfs/api/glfs-handles.h>
12+
int gfapi = 1;
13+
14+
#define LOG_ERR(func, ret) do { \
15+
if (ret != 0) { \
16+
fprintf (stderr, "%s : returned error ret(%d), errno(%d)\n", \
17+
func, ret, errno); \
18+
exit(1); \
19+
} else { \
20+
fprintf (stderr, "%s : returned %d\n", func, ret); \
21+
} \
22+
} while (0)
23+
#define LOG_IF_NO_ERR(func, ret) do { \
24+
if (ret == 0) { \
25+
fprintf (stderr, "%s : hasn't returned error %d\n", \
26+
func, ret); \
27+
exit(1); \
28+
} else { \
29+
fprintf (stderr, "%s : returned %d\n", func, ret); \
30+
} \
31+
} while (0)
32+
int
33+
main (int argc, char *argv[])
34+
{
35+
glfs_t *fs = NULL;
36+
int ret = 0, i;
37+
glfs_fd_t *fd = NULL;
38+
char *filename = "/a1";
39+
char *filename2 = "/a2";
40+
struct stat sb = {0, };
41+
struct callback_arg cbk;
42+
char *logfile = NULL;
43+
char *volname = NULL;
44+
int cnt = 1;
45+
struct callback_inode_arg *in_arg = NULL;
46+
struct glfs_object *root = NULL, *leaf = NULL;
47+
48+
cbk.reason = 0;
49+
50+
fprintf (stderr, "Starting libgfapi_fini\n");
51+
if (argc != 3) {
52+
fprintf (stderr, "Invalid argument\n");
53+
exit(1);
54+
}
55+
56+
volname = argv[1];
57+
logfile = argv[2];
58+
59+
60+
fs = glfs_new (volname);
61+
if (!fs) {
62+
fprintf (stderr, "glfs_new: returned NULL\n");
63+
return 1;
64+
}
65+
66+
ret = glfs_set_volfile_server (fs, "tcp", "localhost", 24007);
67+
LOG_ERR("glfs_set_volfile_server", ret);
68+
69+
ret = glfs_set_logging (fs, logfile, 7);
70+
LOG_ERR("glfs_set_logging", ret);
71+
72+
ret = glfs_init (fs);
73+
LOG_ERR("glfs_init", ret);
74+
75+
sleep (2);
76+
root = glfs_h_lookupat (fs, NULL, "/", &sb, 0);
77+
if (!root) {
78+
ret = -1;
79+
LOG_ERR ("glfs_h_lookupat root", ret);
80+
}
81+
leaf = glfs_h_lookupat (fs, root, filename, &sb, 0);
82+
if (!leaf) {
83+
ret = -1;
84+
LOG_IF_NO_ERR ("glfs_h_lookupat leaf", ret);
85+
}
86+
87+
leaf = glfs_h_creat (fs, root, filename, O_RDWR, 0644, &sb);
88+
if (!leaf) {
89+
ret = -1;
90+
LOG_ERR ("glfs_h_lookupat leaf", ret);
91+
}
92+
fprintf (stderr, "glfs_h_create leaf - %p\n", leaf);
93+
94+
leaf = glfs_h_lookupat (fs, root, filename2, &sb, 0);
95+
if (!leaf) {
96+
ret = -1;
97+
LOG_IF_NO_ERR ("glfs_h_lookupat leaf", ret);
98+
}
99+
100+
ret = glfs_h_rename (fs, root, filename, root, filename2);
101+
LOG_ERR("glfs_rename", ret);
102+
103+
while (cnt++ < 5) {
104+
ret = glfs_h_poll_upcall(fs, &cbk);
105+
LOG_ERR ("glfs_h_poll_upcall", ret);
106+
107+
/* There should not be any upcalls sent */
108+
if (cbk.reason != GFAPI_CBK_EVENT_NULL) {
109+
fprintf (stderr, "Error: Upcall received(%d)\n",
110+
cbk.reason);
111+
exit (1);
112+
}
113+
}
114+
115+
ret = glfs_fini(fs);
116+
LOG_ERR("glfs_fini", ret);
117+
118+
fprintf (stderr, "End of libgfapi_fini\n");
119+
120+
exit(0);
121+
}
122+
123+

tests/basic/gfapi/bug1283983.sh

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/bin/bash
2+
3+
. $(dirname $0)/../../include.rc
4+
. $(dirname $0)/../../volume.rc
5+
6+
cleanup;
7+
8+
TEST glusterd
9+
10+
TEST $CLI volume create $V0 localhost:$B0/brick1;
11+
EXPECT 'Created' volinfo_field $V0 'Status';
12+
13+
TEST $CLI volume start $V0;
14+
EXPECT 'Started' volinfo_field $V0 'Status';
15+
16+
logdir=`gluster --print-logdir`
17+
18+
## Enable Upcall cache-invalidation feature
19+
TEST $CLI volume set $V0 features.cache-invalidation on;
20+
21+
build_tester $(dirname $0)/bug1283983.c -lgfapi -o $(dirname $0)/bug1283983
22+
23+
TEST ./$(dirname $0)/bug1283983 $V0 $logdir/bug1283983.log
24+
25+
## There shouldn't be any NULL gfid messages logged
26+
TEST ! cat $logdir/bug1283983.log | grep "upcall" | grep "00000000-0000-0000-0000-000000000000"
27+
28+
cleanup_tester $(dirname $0)/bug1283983
29+
30+
TEST $CLI volume stop $V0
31+
TEST $CLI volume delete $V0
32+
33+
cleanup;

xlators/features/upcall/src/upcall-internal.c

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -88,16 +88,14 @@ get_cache_invalidation_timeout(xlator_t *this) {
8888
* Allocate and add a new client entry to the given upcall entry
8989
*/
9090
upcall_client_t*
91-
add_upcall_client (call_frame_t *frame, uuid_t gfid,
92-
client_t *client,
91+
add_upcall_client (call_frame_t *frame, client_t *client,
9392
upcall_inode_ctx_t *up_inode_ctx)
9493
{
9594
upcall_client_t *up_client_entry = NULL;
9695

9796
pthread_mutex_lock (&up_inode_ctx->client_list_lock);
9897
{
9998
up_client_entry = __add_upcall_client (frame,
100-
gfid,
10199
client,
102100
up_inode_ctx);
103101
}
@@ -107,8 +105,7 @@ add_upcall_client (call_frame_t *frame, uuid_t gfid,
107105
}
108106

109107
upcall_client_t*
110-
__add_upcall_client (call_frame_t *frame, uuid_t gfid,
111-
client_t *client,
108+
__add_upcall_client (call_frame_t *frame, client_t *client,
112109
upcall_inode_ctx_t *up_inode_ctx)
113110
{
114111
upcall_client_t *up_client_entry = NULL;
@@ -137,11 +134,11 @@ __add_upcall_client (call_frame_t *frame, uuid_t gfid,
137134
}
138135

139136
/*
140-
* Given gfid and client->uid, retrieve the corresponding upcall client entry.
137+
* Given client->uid, retrieve the corresponding upcall client entry.
141138
* If none found, create a new entry.
142139
*/
143140
upcall_client_t*
144-
__get_upcall_client (call_frame_t *frame, uuid_t gfid, client_t *client,
141+
__get_upcall_client (call_frame_t *frame, client_t *client,
145142
upcall_inode_ctx_t *up_inode_ctx)
146143
{
147144
upcall_client_t *up_client_entry = NULL;
@@ -165,7 +162,7 @@ __get_upcall_client (call_frame_t *frame, uuid_t gfid, client_t *client,
165162
}
166163

167164
if (!found_client) { /* create one */
168-
up_client_entry = __add_upcall_client (frame, gfid, client,
165+
up_client_entry = __add_upcall_client (frame, client,
169166
up_inode_ctx);
170167
}
171168

@@ -200,6 +197,7 @@ __upcall_inode_ctx_set (inode_t *inode, xlator_t *this)
200197
INIT_LIST_HEAD (&inode_ctx->inode_ctx_list);
201198
INIT_LIST_HEAD (&inode_ctx->client_list);
202199
inode_ctx->destroy = 0;
200+
gf_uuid_copy (inode_ctx->gfid, inode->gfid);
203201

204202
ctx = (long) inode_ctx;
205203
ret = __inode_ctx_set (inode, this, &ctx);
@@ -458,7 +456,7 @@ upcall_reaper_thread_init (xlator_t *this)
458456
}
459457

460458
/*
461-
* Given a gfid, client, first fetch upcall_entry_t based on gfid.
459+
* Given a client, first fetch upcall_entry_t from the inode_ctx client list.
462460
* Later traverse through the client list of that upcall entry. If this client
463461
* is not present in the list, create one client entry with this client info.
464462
* Also check if there are other clients which need to be notified of this
@@ -502,16 +500,31 @@ upcall_cache_invalidate (call_frame_t *frame, xlator_t *this, client_t *client,
502500
return;
503501
}
504502

503+
/* In case of LOOKUP, if first time, inode created shall be
504+
* invalid till it gets linked to inode table. Read gfid from
505+
* the stat returned in such cases.
506+
*/
507+
if (gf_uuid_is_null (up_inode_ctx->gfid)) {
508+
/* That means inode must have been invalid when this inode_ctx
509+
* is created. Copy the gfid value from stbuf instead.
510+
*/
511+
gf_uuid_copy (up_inode_ctx->gfid, stbuf->ia_gfid);
512+
}
513+
514+
GF_VALIDATE_OR_GOTO ("upcall_cache_invalidate",
515+
!(gf_uuid_is_null (up_inode_ctx->gfid)), out);
505516
pthread_mutex_lock (&up_inode_ctx->client_list_lock);
506517
{
507518
list_for_each_entry_safe (up_client_entry, tmp,
508519
&up_inode_ctx->client_list,
509520
client_list) {
510521

522+
/* Do not send UPCALL event if same client. */
511523
if (!strcmp(client->client_uid,
512524
up_client_entry->client_uid)) {
513525
up_client_entry->access_time = time(NULL);
514526
found = _gf_true;
527+
continue;
515528
}
516529

517530
/*
@@ -532,20 +545,21 @@ upcall_cache_invalidate (call_frame_t *frame, xlator_t *this, client_t *client,
532545
* expire_time_attr to 0.
533546
*/
534547
upcall_client_cache_invalidate(this,
535-
inode->gfid,
548+
up_inode_ctx->gfid,
536549
up_client_entry,
537550
flags, stbuf,
538551
p_stbuf, oldp_stbuf);
539552
}
540553

541554
if (!found) {
542555
up_client_entry = __add_upcall_client (frame,
543-
inode->gfid,
544556
client,
545557
up_inode_ctx);
546558
}
547559
}
548560
pthread_mutex_unlock (&up_inode_ctx->client_list_lock);
561+
out:
562+
return;
549563
}
550564

551565
/*
@@ -565,6 +579,8 @@ upcall_client_cache_invalidate (xlator_t *this, uuid_t gfid,
565579
int ret = -1;
566580
time_t t_expired = time(NULL) - up_client_entry->access_time;
567581

582+
GF_VALIDATE_OR_GOTO ("upcall_client_cache_invalidate",
583+
!(gf_uuid_is_null (gfid)), out);
568584
timeout = get_cache_invalidation_timeout(this);
569585

570586
if (t_expired < timeout) {
@@ -609,6 +625,8 @@ upcall_client_cache_invalidate (xlator_t *this, uuid_t gfid,
609625
__upcall_cleanup_client_entry (up_client_entry);
610626
}
611627
}
628+
out:
629+
return;
612630
}
613631

614632
/*
@@ -640,7 +658,7 @@ upcall_cache_forget (xlator_t *this, inode_t *inode, upcall_inode_ctx_t *up_inod
640658
up_client_entry->access_time = time(NULL);
641659

642660
upcall_client_cache_invalidate(this,
643-
inode->gfid,
661+
up_inode_ctx->gfid,
644662
up_client_entry,
645663
flags, NULL,
646664
NULL, NULL);

xlators/features/upcall/src/upcall.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ up_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
161161
}
162162
flags = UP_UPDATE_CLIENT;
163163
upcall_cache_invalidate (frame, this, client, local->inode, flags,
164-
NULL, NULL, NULL);
164+
stbuf, NULL, NULL);
165165

166166
out:
167167
UPCALL_STACK_UNWIND (readv, frame, op_ret, op_errno, vector,
@@ -747,7 +747,7 @@ up_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
747747
}
748748
flags = UP_UPDATE_CLIENT;
749749
upcall_cache_invalidate (frame, this, client, local->inode, flags,
750-
NULL, NULL, NULL);
750+
stbuf, NULL, NULL);
751751

752752
out:
753753
UPCALL_STACK_UNWIND (lookup, frame, op_ret, op_errno, inode, stbuf,
@@ -804,7 +804,7 @@ up_stat_cbk (call_frame_t *frame, void *cookie,
804804
}
805805
flags = UP_UPDATE_CLIENT;
806806
upcall_cache_invalidate (frame, this, client, local->inode, flags,
807-
NULL, NULL, NULL);
807+
buf, NULL, NULL);
808808

809809
out:
810810
UPCALL_STACK_UNWIND (stat, frame, op_ret, op_errno, buf,
@@ -970,7 +970,7 @@ up_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
970970
}
971971
flags = UP_UPDATE_CLIENT;
972972
upcall_cache_invalidate (frame, this, client, local->inode, flags,
973-
NULL, NULL, NULL);
973+
stbuf, NULL, NULL);
974974

975975
out:
976976
UPCALL_STACK_UNWIND (readlink, frame, op_ret, op_errno, path, stbuf,

xlators/features/upcall/src/upcall.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ struct _upcall_inode_ctx_t {
7272
pthread_mutex_t client_list_lock; /* mutex for clients list
7373
of this upcall entry */
7474
int destroy;
75+
uuid_t gfid; /* gfid of the entry */
7576
};
7677
typedef struct _upcall_inode_ctx_t upcall_inode_ctx_t;
7778

@@ -89,14 +90,11 @@ typedef struct upcall_local upcall_local_t;
8990
void upcall_local_wipe (xlator_t *this, upcall_local_t *local);
9091
upcall_local_t *upcall_local_init (call_frame_t *frame, xlator_t *this, inode_t *inode);
9192

92-
upcall_client_t *add_upcall_client (call_frame_t *frame, uuid_t gfid,
93-
client_t *client,
93+
upcall_client_t *add_upcall_client (call_frame_t *frame, client_t *client,
9494
upcall_inode_ctx_t *up_inode_ctx);
95-
upcall_client_t *__add_upcall_client (call_frame_t *frame, uuid_t gfid,
96-
client_t *client,
95+
upcall_client_t *__add_upcall_client (call_frame_t *frame, client_t *client,
9796
upcall_inode_ctx_t *up_inode_ctx);
98-
upcall_client_t *__get_upcall_client (call_frame_t *frame, uuid_t gfid,
99-
client_t *client,
97+
upcall_client_t *__get_upcall_client (call_frame_t *frame, client_t *client,
10098
upcall_inode_ctx_t *up_inode_ctx);
10199
int __upcall_cleanup_client_entry (upcall_client_t *up_client);
102100
int upcall_cleanup_expired_clients (xlator_t *this,

0 commit comments

Comments
 (0)