The Samba-Bugzilla – Attachment 12286 Details for
Bug 5324
Reduce the performance penalty of --xattrs on Mac OS X
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
valgrind clean work in progress patch
rsync-xattr-hashtable-try-02.patches.txt (text/plain), 25.20 KB, created by
Stefan Metzmacher
on 2016-07-25 07:07:43 UTC
(
hide
)
Description:
valgrind clean work in progress patch
Filename:
MIME Type:
Creator:
Stefan Metzmacher
Created:
2016-07-25 07:07:43 UTC
Size:
25.20 KB
patch
obsolete
>From cd0b699648063e6dc13b433e5e0ba0bbf4d3549d Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 22 Jul 2016 14:43:27 +0200 >Subject: [PATCH 1/7] xattrs: add some const to empty_xattr > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > xattrs.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > >diff --git a/xattrs.c b/xattrs.c >index 0658afb..ed8c81b 100644 >--- a/xattrs.c >+++ b/xattrs.c >@@ -82,7 +82,7 @@ typedef struct { > static size_t namebuf_len = 0; > static char *namebuf = NULL; > >-static item_list empty_xattr = EMPTY_ITEM_LIST; >+static const item_list empty_xattr = EMPTY_ITEM_LIST; > static item_list rsync_xal_l = EMPTY_ITEM_LIST; > > static size_t prior_xattr_count = (size_t)-1; >@@ -466,7 +466,7 @@ int send_xattr(int f, stat_x *sxp) > * need so that send_xattr_request() can tell the sender about them. */ > int xattr_diff(struct file_struct *file, stat_x *sxp, int find_all) > { >- item_list *lst = rsync_xal_l.items; >+ const item_list *lst = rsync_xal_l.items; > rsync_xa *snd_rxa, *rec_rxa; > int snd_cnt, rec_cnt; > int cmp, same, xattrs_equal = 1; >-- >1.9.1 > > >From d2923e0087a520fa778a0350790af5eb74ccd677 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 22 Jul 2016 18:14:40 +0200 >Subject: [PATCH 2/7] xattrs: let rsync_xal_store() return ndx. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > xattrs.c | 10 +++++----- > 1 file changed, 5 insertions(+), 5 deletions(-) > >diff --git a/xattrs.c b/xattrs.c >index ed8c81b..88da5ee 100644 >--- a/xattrs.c >+++ b/xattrs.c >@@ -398,8 +398,9 @@ static int find_matching_xattr(item_list *xalp) > } > > /* Store *xalp on the end of rsync_xal_l */ >-static void rsync_xal_store(item_list *xalp) >+static int rsync_xal_store(item_list *xalp) > { >+ int ndx = rsync_xal_l.count; /* pre-incremented count */ > item_list *new_lst = EXPAND_ITEM_LIST(&rsync_xal_l, item_list, RSYNC_XAL_LIST_INITIAL); > /* Since the following call starts a new list, we know it will hold the > * entire initial-count, not just enough space for one new item. */ >@@ -408,6 +409,7 @@ static void rsync_xal_store(item_list *xalp) > memcpy(new_lst->items, xalp->items, xalp->count * sizeof (rsync_xa)); > new_lst->count = xalp->count; > xalp->count = 0; >+ return ndx; > } > > /* Send the make_xattr()-generated xattr list for this flist entry. */ >@@ -454,8 +456,7 @@ int send_xattr(int f, stat_x *sxp) > else > write_bigbuf(f, rxa->datum, rxa->datum_len); > } >- ndx = rsync_xal_l.count; /* pre-incremented count */ >- rsync_xal_store(sxp->xattr); /* adds item to rsync_xal_l */ >+ ndx = rsync_xal_store(sxp->xattr); /* adds item to rsync_xal_l */ > } > > return ndx; >@@ -769,8 +770,7 @@ void receive_xattr(int f, struct file_struct *file) > if (need_sort && count > 1) > qsort(temp_xattr.items, count, sizeof (rsync_xa), rsync_xal_compare_names); > >- ndx = rsync_xal_l.count; /* pre-incremented count */ >- rsync_xal_store(&temp_xattr); /* adds item to rsync_xal_l */ >+ ndx = rsync_xal_store(&temp_xattr); /* adds item to rsync_xal_l */ > > F_XATTR(file) = ndx; > } >-- >1.9.1 > > >From 14cae4c994ed5e868d61aa42f133acbb1e43e0b4 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 22 Jul 2016 18:32:04 +0200 >Subject: [PATCH 3/7] xattrs: introduce a rsync_xa_list struct as layer between > two nested item_lists > >We have the global 'item_list rsync_xal_l', this maintains an array >of rsync_xa_list structure, one per file. > >Each rsync_xa_list structure maintains an array of rsync_xa structure, >while each represent a single xattr with name and value. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > xattrs.c | 71 +++++++++++++++++++++++++++++++++++++++++----------------------- > 1 file changed, 46 insertions(+), 25 deletions(-) > >diff --git a/xattrs.c b/xattrs.c >index 88da5ee..5051492 100644 >--- a/xattrs.c >+++ b/xattrs.c >@@ -79,9 +79,16 @@ typedef struct { > int num; > } rsync_xa; > >+typedef struct { >+ item_list xa_items; >+} rsync_xa_list; >+ > static size_t namebuf_len = 0; > static char *namebuf = NULL; > >+static const rsync_xa_list empty_xa_list = { >+ .xa_items = EMPTY_ITEM_LIST, >+}; > static const item_list empty_xattr = EMPTY_ITEM_LIST; > static item_list rsync_xal_l = EMPTY_ITEM_LIST; > >@@ -360,14 +367,16 @@ int copy_xattrs(const char *source, const char *dest) > return 0; > } > >-static int find_matching_xattr(item_list *xalp) >+static int find_matching_xattr(const item_list *xalp) > { >- size_t i, j; >- item_list *lst = rsync_xal_l.items; >+ const rsync_xa_list *glst = rsync_xal_l.items; >+ size_t i; > > for (i = 0; i < rsync_xal_l.count; i++) { >- rsync_xa *rxas1 = lst[i].items; >- rsync_xa *rxas2 = xalp->items; >+ const item_list *lst = &glst[i].xa_items; >+ const rsync_xa *rxas1 = lst[i].items; >+ const rsync_xa *rxas2 = xalp->items; >+ size_t j; > > /* Wrong number of elements? */ > if (lst[i].count != xalp->count) >@@ -401,13 +410,13 @@ static int find_matching_xattr(item_list *xalp) > static int rsync_xal_store(item_list *xalp) > { > int ndx = rsync_xal_l.count; /* pre-incremented count */ >- item_list *new_lst = EXPAND_ITEM_LIST(&rsync_xal_l, item_list, RSYNC_XAL_LIST_INITIAL); >+ rsync_xa_list *new_list = EXPAND_ITEM_LIST(&rsync_xal_l, rsync_xa_list, RSYNC_XAL_LIST_INITIAL); > /* Since the following call starts a new list, we know it will hold the > * entire initial-count, not just enough space for one new item. */ >- *new_lst = empty_xattr; >- (void)EXPAND_ITEM_LIST(new_lst, rsync_xa, xalp->count); >- memcpy(new_lst->items, xalp->items, xalp->count * sizeof (rsync_xa)); >- new_lst->count = xalp->count; >+ *new_list = empty_xa_list; >+ (void)EXPAND_ITEM_LIST(&new_list->xa_items, rsync_xa, xalp->count); >+ memcpy(new_list->xa_items.items, xalp->items, xalp->count * sizeof (rsync_xa)); >+ new_list->xa_items.count = xalp->count; > xalp->count = 0; > return ndx; > } >@@ -467,7 +476,8 @@ int send_xattr(int f, stat_x *sxp) > * need so that send_xattr_request() can tell the sender about them. */ > int xattr_diff(struct file_struct *file, stat_x *sxp, int find_all) > { >- const item_list *lst = rsync_xal_l.items; >+ const rsync_xa_list *glst = rsync_xal_l.items; >+ const item_list *lst = NULL; > rsync_xa *snd_rxa, *rec_rxa; > int snd_cnt, rec_cnt; > int cmp, same, xattrs_equal = 1; >@@ -480,10 +490,12 @@ int xattr_diff(struct file_struct *file, stat_x *sxp, int find_all) > rec_cnt = 0; > } > >- if (F_XATTR(file) >= 0) >- lst += F_XATTR(file); >- else >+ if (F_XATTR(file) >= 0) { >+ glst += F_XATTR(file); >+ lst = &glst->xa_items; >+ } else { > lst = &empty_xattr; >+ } > > snd_rxa = lst->items; > snd_cnt = lst->count; >@@ -541,11 +553,14 @@ int xattr_diff(struct file_struct *file, stat_x *sxp, int find_all) > * XSTATE_ABBREV states into XSTATE_DONE. */ > void send_xattr_request(const char *fname, struct file_struct *file, int f_out) > { >- item_list *lst = rsync_xal_l.items; >+ const rsync_xa_list *glst = rsync_xal_l.items; >+ const item_list *lst = NULL; > int cnt, prior_req = 0; > rsync_xa *rxa; > >- lst += F_XATTR(file); >+ glst += F_XATTR(file); >+ lst = &glst->xa_items; >+ > for (rxa = lst->items, cnt = lst->count; cnt--; rxa++) { > if (rxa->datum_len <= MAX_FULL_DATUM) > continue; >@@ -596,7 +611,8 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out) > * stores it in place of its checksum. */ > int recv_xattr_request(struct file_struct *file, int f_in) > { >- item_list *lst = rsync_xal_l.items; >+ const rsync_xa_list *glst = rsync_xal_l.items; >+ const item_list *lst = NULL; > char *old_datum, *name; > rsync_xa *rxa; > int rel_pos, cnt, num, got_xattr_data = 0; >@@ -605,7 +621,8 @@ int recv_xattr_request(struct file_struct *file, int f_in) > rprintf(FERROR, "recv_xattr_request: internal data error!\n"); > exit_cleanup(RERR_PROTOCOL); > } >- lst += F_XATTR(file); >+ glst += F_XATTR(file); >+ lst = &glst->xa_items; > > cnt = lst->count; > rxa = lst->items; >@@ -796,12 +813,13 @@ void cache_tmp_xattr(struct file_struct *file, stat_x *sxp) > void uncache_tmp_xattrs(void) > { > if (prior_xattr_count != (size_t)-1) { >- item_list *xattr_item = rsync_xal_l.items; >- item_list *xattr_start = xattr_item + prior_xattr_count; >- xattr_item += rsync_xal_l.count; >+ rsync_xa_list *xa_list_item = rsync_xal_l.items; >+ rsync_xa_list *xa_list_start = xa_list_item + prior_xattr_count; >+ xa_list_item += rsync_xal_l.count; > rsync_xal_l.count = prior_xattr_count; >- while (xattr_item-- > xattr_start) >- rsync_xal_free(xattr_item); >+ while (xa_list_item-- > xa_list_start) { >+ rsync_xal_free(&xa_list_item->xa_items); >+ } > prior_xattr_count = (size_t)-1; > } > } >@@ -921,8 +939,9 @@ static int rsync_xal_set(const char *fname, item_list *xalp, > int set_xattr(const char *fname, const struct file_struct *file, > const char *fnamecmp, stat_x *sxp) > { >+ rsync_xa_list *glst = rsync_xal_l.items; >+ item_list *lst = NULL; > int ndx; >- item_list *lst = rsync_xal_l.items; > > if (dry_run) > return 1; /* FIXME: --dry-run needs to compute this value */ >@@ -952,7 +971,9 @@ int set_xattr(const char *fname, const struct file_struct *file, > #endif > > ndx = F_XATTR(file); >- return rsync_xal_set(fname, lst + ndx, fnamecmp, sxp); >+ glst += ndx; >+ lst = &glst->xa_items; >+ return rsync_xal_set(fname, lst, fnamecmp, sxp); > } > > #ifdef SUPPORT_ACLS >-- >1.9.1 > > >From 0ecc4dc6850e68bfa01c8e6415483f545a4fff60 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 22 Jul 2016 18:35:18 +0200 >Subject: [PATCH 4/7] TODO: hashtable: add hashlittle() > >--- > hashtable.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 170 insertions(+) > >diff --git a/hashtable.c b/hashtable.c >index f0fbe51..458d61b 100644 >--- a/hashtable.c >+++ b/hashtable.c >@@ -170,3 +170,173 @@ void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing) > tbl->entries++; > return node; > } >+ >+#ifndef WORDS_BIGENDIAN >+# define HASH_LITTLE_ENDIAN 1 >+# define HASH_BIG_ENDIAN 0 >+#else >+# define HASH_LITTLE_ENDIAN 0 >+# define HASH_BIG_ENDIAN 1 >+#endif >+ >+#define hashsize(n) ((uint32_t)1<<(n)) >+#define hashmask(n) (hashsize(n)-1) >+#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) >+ >+#define mix(a,b,c) \ >+{ \ >+ a -= c; a ^= rot(c, 4); c += b; \ >+ b -= a; b ^= rot(a, 6); a += c; \ >+ c -= b; c ^= rot(b, 8); b += a; \ >+ a -= c; a ^= rot(c,16); c += b; \ >+ b -= a; b ^= rot(a,19); a += c; \ >+ c -= b; c ^= rot(b, 4); b += a; \ >+} >+ >+#define final(a,b,c) \ >+{ \ >+ c ^= b; c -= rot(b,14); \ >+ a ^= c; a -= rot(c,11); \ >+ b ^= a; b -= rot(a,25); \ >+ c ^= b; c -= rot(b,16); \ >+ a ^= c; a -= rot(c,4); \ >+ b ^= a; b -= rot(a,14); \ >+ c ^= b; c -= rot(b,24); \ >+} >+ >+ >+uint32_t hashlittle(const void *key, size_t length) >+{ >+ uint32_t a,b,c; /* internal state */ >+ union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */ >+ >+ /* Set up the internal state */ >+ a = b = c = 0xdeadbeef + ((uint32_t)length); >+ >+ u.ptr = key; >+ if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { >+ const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ >+ const uint8_t *k8; >+ >+ /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ >+ while (length > 12) >+ { >+ a += k[0]; >+ b += k[1]; >+ c += k[2]; >+ mix(a,b,c); >+ length -= 12; >+ k += 3; >+ } >+ >+ /*----------------------------- handle the last (probably partial) block */ >+ k8 = (const uint8_t *)k; >+ switch(length) >+ { >+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; >+ case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ >+ case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ >+ case 9 : c+=k8[8]; /* fall through */ >+ case 8 : b+=k[1]; a+=k[0]; break; >+ case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ >+ case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ >+ case 5 : b+=k8[4]; /* fall through */ >+ case 4 : a+=k[0]; break; >+ case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ >+ case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ >+ case 1 : a+=k8[0]; break; >+ case 0 : return c; >+ } >+ } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { >+ const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ >+ const uint8_t *k8; >+ >+ /*--------------- all but last block: aligned reads and different mixing */ >+ while (length > 12) >+ { >+ a += k[0] + (((uint32_t)k[1])<<16); >+ b += k[2] + (((uint32_t)k[3])<<16); >+ c += k[4] + (((uint32_t)k[5])<<16); >+ mix(a,b,c); >+ length -= 12; >+ k += 6; >+ } >+ >+ /*----------------------------- handle the last (probably partial) block */ >+ k8 = (const uint8_t *)k; >+ switch(length) >+ { >+ case 12: c+=k[4]+(((uint32_t)k[5])<<16); >+ b+=k[2]+(((uint32_t)k[3])<<16); >+ a+=k[0]+(((uint32_t)k[1])<<16); >+ break; >+ case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ >+ case 10: c+=k[4]; >+ b+=k[2]+(((uint32_t)k[3])<<16); >+ a+=k[0]+(((uint32_t)k[1])<<16); >+ break; >+ case 9 : c+=k8[8]; /* fall through */ >+ case 8 : b+=k[2]+(((uint32_t)k[3])<<16); >+ a+=k[0]+(((uint32_t)k[1])<<16); >+ break; >+ case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ >+ case 6 : b+=k[2]; >+ a+=k[0]+(((uint32_t)k[1])<<16); >+ break; >+ case 5 : b+=k8[4]; /* fall through */ >+ case 4 : a+=k[0]+(((uint32_t)k[1])<<16); >+ break; >+ case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ >+ case 2 : a+=k[0]; >+ break; >+ case 1 : a+=k8[0]; >+ break; >+ case 0 : return c; /* zero length requires no mixing */ >+ } >+ >+ } else { /* need to read the key one byte at a time */ >+ const uint8_t *k = (const uint8_t *)key; >+ >+ /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ >+ while (length > 12) >+ { >+ a += k[0]; >+ a += ((uint32_t)k[1])<<8; >+ a += ((uint32_t)k[2])<<16; >+ a += ((uint32_t)k[3])<<24; >+ b += k[4]; >+ b += ((uint32_t)k[5])<<8; >+ b += ((uint32_t)k[6])<<16; >+ b += ((uint32_t)k[7])<<24; >+ c += k[8]; >+ c += ((uint32_t)k[9])<<8; >+ c += ((uint32_t)k[10])<<16; >+ c += ((uint32_t)k[11])<<24; >+ mix(a,b,c); >+ length -= 12; >+ k += 12; >+ } >+ >+ /*-------------------------------- last block: affect all 32 bits of (c) */ >+ switch(length) /* all the case statements fall through */ >+ { >+ case 12: c+=((uint32_t)k[11])<<24; >+ case 11: c+=((uint32_t)k[10])<<16; >+ case 10: c+=((uint32_t)k[9])<<8; >+ case 9 : c+=k[8]; >+ case 8 : b+=((uint32_t)k[7])<<24; >+ case 7 : b+=((uint32_t)k[6])<<16; >+ case 6 : b+=((uint32_t)k[5])<<8; >+ case 5 : b+=k[4]; >+ case 4 : a+=((uint32_t)k[3])<<24; >+ case 3 : a+=((uint32_t)k[2])<<16; >+ case 2 : a+=((uint32_t)k[1])<<8; >+ case 1 : a+=k[0]; >+ break; >+ case 0 : return c; >+ } >+ } >+ >+ final(a,b,c); >+ return c; >+} >-- >1.9.1 > > >From bdf0fc355fee214e4962233dd55b62295214b650 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 22 Jul 2016 19:18:58 +0200 >Subject: [PATCH 5/7] CHECK fix find_matching_xattr()??? > >--- > xattrs.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > >diff --git a/xattrs.c b/xattrs.c >index 5051492..fa4128d 100644 >--- a/xattrs.c >+++ b/xattrs.c >@@ -374,12 +374,12 @@ static int find_matching_xattr(const item_list *xalp) > > for (i = 0; i < rsync_xal_l.count; i++) { > const item_list *lst = &glst[i].xa_items; >- const rsync_xa *rxas1 = lst[i].items; >+ const rsync_xa *rxas1 = lst->items; > const rsync_xa *rxas2 = xalp->items; > size_t j; > > /* Wrong number of elements? */ >- if (lst[i].count != xalp->count) >+ if (lst->count != xalp->count) > continue; > /* any elements different? */ > for (j = 0; j < xalp->count; j++) { >-- >1.9.1 > > >From 685a176df67419efa0a6bd9db4b0a5a43d4439a2 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 22 Jul 2016 19:46:46 +0200 >Subject: [PATCH 6/7] faster!!! > >--- > hashtable.c | 1 + > xattrs.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- > 2 files changed, 118 insertions(+), 8 deletions(-) > >diff --git a/hashtable.c b/hashtable.c >index 458d61b..6dd7918 100644 >--- a/hashtable.c >+++ b/hashtable.c >@@ -76,6 +76,7 @@ void *hashtable_find(struct hashtable *tbl, int64 key, int allocate_if_missing) > > if (key64 ? key == 0 : (int32)key == 0) { > rprintf(FERROR, "Internal hashtable error: illegal key supplied!\n"); >+ abort(); > exit_cleanup(RERR_MESSAGEIO); > } > >diff --git a/xattrs.c b/xattrs.c >index fa4128d..5c09aeb 100644 >--- a/xattrs.c >+++ b/xattrs.c >@@ -79,7 +79,10 @@ typedef struct { > int num; > } rsync_xa; > >-typedef struct { >+typedef struct _rsync_xa_list { >+ struct _rsync_xa_list *next; >+ int64 key; >+ int ndx; > item_list xa_items; > } rsync_xa_list; > >@@ -91,6 +94,7 @@ static const rsync_xa_list empty_xa_list = { > }; > static const item_list empty_xattr = EMPTY_ITEM_LIST; > static item_list rsync_xal_l = EMPTY_ITEM_LIST; >+static struct hashtable *rsync_xal_h = NULL; > > static size_t prior_xattr_count = (size_t)-1; > >@@ -367,19 +371,56 @@ int copy_xattrs(const char *source, const char *dest) > return 0; > } > >-static int find_matching_xattr(const item_list *xalp) >+static int64 xattr_lookup_hash(const item_list *xalp) > { >- const rsync_xa_list *glst = rsync_xal_l.items; >+ const rsync_xa *rxas = xalp->items; > size_t i; >+ int64 key = hashlittle(&xalp->count, sizeof(xalp->count)); >+ >+ for (i = 0; i < xalp->count; i++) { >+ key += hashlittle(rxas[i].name, rxas[i].name_len); >+ if (rxas[i].datum_len > MAX_FULL_DATUM) { >+ key += hashlittle(rxas[i].datum, MAX_DIGEST_LEN); >+ } else { >+ key += hashlittle(rxas[i].datum, rxas[i].datum_len); >+ } >+ } >+ >+ if (key == 0) { >+// return 1; >+ } >+ >+ return key; >+} >+ >+static int find_matching_xattr(const item_list *xalp) >+{ >+ struct ht_int64_node *node = NULL; >+ int64 key; >+ rsync_xa_list *ptr = NULL; >+ >+ if (rsync_xal_h == NULL) { >+ return -1; >+ } >+ >+ key = xattr_lookup_hash(xalp); >+ >+ node = hashtable_find(rsync_xal_h, key, 0); >+ if (node == NULL) { >+ return -1; >+ } > >- for (i = 0; i < rsync_xal_l.count; i++) { >- const item_list *lst = &glst[i].xa_items; >- const rsync_xa *rxas1 = lst->items; >+ if (node->data == NULL) { >+ return -1; >+ } >+ >+ for (ptr = node->data; ptr != NULL; ptr = ptr->next) { >+ const rsync_xa *rxas1 = ptr->xa_items.items; > const rsync_xa *rxas2 = xalp->items; > size_t j; > > /* Wrong number of elements? */ >- if (lst->count != xalp->count) >+ if (ptr->xa_items.count != xalp->count) > continue; > /* any elements different? */ > for (j = 0; j < xalp->count; j++) { >@@ -400,7 +441,7 @@ static int find_matching_xattr(const item_list *xalp) > } > /* no differences found. This is The One! */ > if (j == xalp->count) >- return i; >+ return ptr->ndx; > } > > return -1; >@@ -409,6 +450,7 @@ static int find_matching_xattr(const item_list *xalp) > /* Store *xalp on the end of rsync_xal_l */ > static int rsync_xal_store(item_list *xalp) > { >+ struct ht_int64_node *node = NULL; > int ndx = rsync_xal_l.count; /* pre-incremented count */ > rsync_xa_list *new_list = EXPAND_ITEM_LIST(&rsync_xal_l, rsync_xa_list, RSYNC_XAL_LIST_INITIAL); > /* Since the following call starts a new list, we know it will hold the >@@ -418,6 +460,38 @@ static int rsync_xal_store(item_list *xalp) > memcpy(new_list->xa_items.items, xalp->items, xalp->count * sizeof (rsync_xa)); > new_list->xa_items.count = xalp->count; > xalp->count = 0; >+ >+ new_list->key = xattr_lookup_hash(&new_list->xa_items); >+ new_list->ndx = ndx; >+ >+ if (rsync_xal_h == NULL) { >+ rsync_xal_h = hashtable_create(512, 1); >+ } >+ if (rsync_xal_h == NULL) { >+ out_of_memory("rsync_xal_h hashtable_create()"); >+ } >+ >+ node = hashtable_find(rsync_xal_h, new_list->key, 1); >+ if (node == NULL) { >+ out_of_memory("rsync_xal_h hashtable_find()"); >+ } >+ >+ if (node->data != NULL) { >+ rsync_xa_list *ptr = node->data; >+ >+ while (ptr != NULL) { >+ if (ptr->next != NULL) { >+ ptr = ptr->next; >+ continue; >+ } >+ >+ ptr->next = new_list; >+ break; >+ } >+ } else { >+ node->data = new_list; >+ } >+ > return ndx; > } > >@@ -818,7 +892,42 @@ void uncache_tmp_xattrs(void) > xa_list_item += rsync_xal_l.count; > rsync_xal_l.count = prior_xattr_count; > while (xa_list_item-- > xa_list_start) { >+ struct ht_int64_node *node = NULL; >+ rsync_xa_list *ptr = NULL; >+ > rsync_xal_free(&xa_list_item->xa_items); >+ >+ if (rsync_xal_h == NULL) { >+ continue; >+ } >+ >+ node = hashtable_find(rsync_xal_h, xa_list_item->key, 0); >+ if (node == NULL) { >+ continue; >+ } >+ >+ if (node->data == NULL) { >+ continue; >+ } >+ >+ ptr = node->data; >+ if (xa_list_item == ptr) { >+ /* >+ * xa_list_item is the first in the list >+ */ >+ node->data = xa_list_item->next; >+ xa_list_item->next = NULL; >+ continue; >+ } >+ >+ while (ptr != NULL) { >+ if (xa_list_item == ptr->next) { >+ ptr->next = xa_list_item->next; >+ xa_list_item->next = NULL; >+ break; >+ } >+ ptr = ptr->next; >+ } > } > prior_xattr_count = (size_t)-1; > } >-- >1.9.1 > > >From 92f6071a3c3e047f6748c7e5eb36c895a7fcda05 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sat, 23 Jul 2016 11:59:06 +0200 >Subject: [PATCH 7/7] next try > >--- > xattrs.c | 70 ++++++++++++++++++++++++++++++++++++++++++---------------------- > 1 file changed, 46 insertions(+), 24 deletions(-) > >diff --git a/xattrs.c b/xattrs.c >index 5c09aeb..86a96ac 100644 >--- a/xattrs.c >+++ b/xattrs.c >@@ -79,10 +79,16 @@ typedef struct { > int num; > } rsync_xa; > >+struct _rsync_xa_list; >+ >+typedef struct _rsync_xa_list_ref { >+ struct _rsync_xa_list_ref *next; >+ int ndx; >+} rsync_xa_list_ref; >+ > typedef struct _rsync_xa_list { >- struct _rsync_xa_list *next; >- int64 key; > int ndx; >+ int64 key; > item_list xa_items; > } rsync_xa_list; > >@@ -395,9 +401,9 @@ static int64 xattr_lookup_hash(const item_list *xalp) > > static int find_matching_xattr(const item_list *xalp) > { >- struct ht_int64_node *node = NULL; >+ const struct ht_int64_node *node = NULL; >+ const rsync_xa_list_ref *ref = NULL; > int64 key; >- rsync_xa_list *ptr = NULL; > > if (rsync_xal_h == NULL) { > return -1; >@@ -414,11 +420,15 @@ static int find_matching_xattr(const item_list *xalp) > return -1; > } > >- for (ptr = node->data; ptr != NULL; ptr = ptr->next) { >- const rsync_xa *rxas1 = ptr->xa_items.items; >+ for (ref = node->data; ref != NULL; ref = ref->next) { >+ const rsync_xa_list *ptr = rsync_xal_l.items; >+ const rsync_xa *rxas1 = NULL; > const rsync_xa *rxas2 = xalp->items; > size_t j; > >+ ptr += ref->ndx; >+ rxas1 = ptr->xa_items.items; >+ > /* Wrong number of elements? */ > if (ptr->xa_items.count != xalp->count) > continue; >@@ -441,7 +451,7 @@ static int find_matching_xattr(const item_list *xalp) > } > /* no differences found. This is The One! */ > if (j == xalp->count) >- return ptr->ndx; >+ return ref->ndx; > } > > return -1; >@@ -453,6 +463,7 @@ static int rsync_xal_store(item_list *xalp) > struct ht_int64_node *node = NULL; > int ndx = rsync_xal_l.count; /* pre-incremented count */ > rsync_xa_list *new_list = EXPAND_ITEM_LIST(&rsync_xal_l, rsync_xa_list, RSYNC_XAL_LIST_INITIAL); >+ rsync_xa_list_ref *new_ref = NULL; > /* Since the following call starts a new list, we know it will hold the > * entire initial-count, not just enough space for one new item. */ > *new_list = empty_xa_list; >@@ -461,8 +472,8 @@ static int rsync_xal_store(item_list *xalp) > new_list->xa_items.count = xalp->count; > xalp->count = 0; > >- new_list->key = xattr_lookup_hash(&new_list->xa_items); > new_list->ndx = ndx; >+ new_list->key = xattr_lookup_hash(&new_list->xa_items); > > if (rsync_xal_h == NULL) { > rsync_xal_h = hashtable_create(512, 1); >@@ -476,20 +487,27 @@ static int rsync_xal_store(item_list *xalp) > out_of_memory("rsync_xal_h hashtable_find()"); > } > >+ new_ref = new0(rsync_xa_list_ref); >+ if (new_ref == NULL) { >+ out_of_memory("new0(rsync_xa_list_ref)"); >+ } >+ >+ new_ref->ndx = ndx; >+ > if (node->data != NULL) { >- rsync_xa_list *ptr = node->data; >+ rsync_xa_list_ref *ref = node->data; > >- while (ptr != NULL) { >- if (ptr->next != NULL) { >- ptr = ptr->next; >+ while (ref != NULL) { >+ if (ref->next != NULL) { >+ ref = ref->next; > continue; > } > >- ptr->next = new_list; >+ ref->next = new_ref; > break; > } > } else { >- node->data = new_list; >+ node->data = new_ref; > } > > return ndx; >@@ -893,7 +911,7 @@ void uncache_tmp_xattrs(void) > rsync_xal_l.count = prior_xattr_count; > while (xa_list_item-- > xa_list_start) { > struct ht_int64_node *node = NULL; >- rsync_xa_list *ptr = NULL; >+ rsync_xa_list_ref *ref = NULL; > > rsync_xal_free(&xa_list_item->xa_items); > >@@ -910,23 +928,27 @@ void uncache_tmp_xattrs(void) > continue; > } > >- ptr = node->data; >- if (xa_list_item == ptr) { >+ ref = node->data; >+ if (xa_list_item->ndx == ref->ndx) { > /* > * xa_list_item is the first in the list > */ >- node->data = xa_list_item->next; >- xa_list_item->next = NULL; >+ node->data = ref->next; >+ free(ref); > continue; > } > >- while (ptr != NULL) { >- if (xa_list_item == ptr->next) { >- ptr->next = xa_list_item->next; >- xa_list_item->next = NULL; >+ while (ref != NULL) { >+ if (ref->next == NULL) { >+ ref = NULL; >+ break; >+ } >+ if (xa_list_item->ndx == ref->next->ndx) { >+ ref->next = ref->next->next; >+ free(ref); > break; > } >- ptr = ptr->next; >+ ref = ref->next; > } > } > prior_xattr_count = (size_t)-1; >-- >1.9.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 5324
:
12285
|
12286
|
12287