Viacheslav Dubeyko <Slava.Dubeyko@xxxxxxx> wrote: > > if (unlikely(group != netfs_group) && > > - group != NETFS_FOLIO_COPY_TO_CACHE) > > + group != NETFS_FOLIO_COPY_TO_CACHE && > > + (group || folio_test_dirty(folio))) > > I am trying to follow to this complex condition. Is it possible case that > folio is dirty but we don't flush the content? It's slightly complicated by fscache. The way I have made local caching work for things that use netfslib fully is that the writeback code copies the data to the cache. We achieve this by marking the pages dirty when we read them from the server. However, so that we don't *also* write the clean data back to the server, the writeback group[*] field is set to a special value (NETFS_FOLIO_COPY_TO_CACHE) and we make the assumption that the writeback group is only actually going to be used by the filesystem if the page is actually modified - in which case the writeback group field is overwritten. [*] This is either folio->private or in a netfs_folio struct attached to folio->private. Note that folio->private is set to be removed in the future. In the event that a page is modified it will be written back to the server(s) and the cache, assuming there is a cache. Also note the netfs_io_stream struct. There are two in the netfs_io_request struct and these are used to separately manage and divide up the writes to a server and to the cache. I've also left the possibility open that we can have more than two streams in the event that we need to write the data to multiple servers. Further, another reason for making writeback write the data to both the cache and the server is that if you are using content encryption, the data is encrypted and then the ciphertext is written to both the server and the cache. > Is it possible case that folio is dirty but we don't flush the content? Anyway, to answer the question more specifically, yes. If the folio is dirty and in the same writeback group (e.g. most recent ceph snap context), then we can presumably keep modifying it. And if the folio is marked dirty and is marked NETFS_FOLIO_COPY_TO_CACHE, then we can just overwrite it, replace or clear the NETFS_FOLIO_COPY_TO_CACHE mark and then it just becomes a regular dirty page. It will get written to fscache either way. > > + if ((++flush_counter & 0xf) == 0xf) > > + msleep(10); > > Do we really need to use sleep? And why is it 10 ms? And even if we would > like to use sleep, then it is better to introduce the named constant. And > what is teh justification for 10 ms? At the moment, debugging and stopping it from running wild in a tight loop when a mistake is made. Remember: at this point, this is a WIP. But in reality, we might see this if we're indulging in cache ping-pong between two clients. I'm not sure how this might be mitigated in the ceph environment - if that's not already done. > > - kdebug("wrong group"); > > + kdebug("wrong group %px != %px", fgroup, wreq->group); > > I believe to use the %px is not very good practice. Do we really need to show > the real pointer? At some point I need to test interference from someone cranking the snaps and I'll probably need this then - though it might be better to make a tracepoint for it. > > +/* > > + * Get a ref on a netfs group attached to a dirty page (e.g. a ceph snap). > > + */ > > +static inline struct netfs_group *netfs_get_group(struct netfs_group *netfs_group) > > +{ > > + if (netfs_group && netfs_group != NETFS_FOLIO_COPY_TO_CACHE) > > The netfs_group is a pointer. Is it correct comparison of pointer with the > NETFS_FOLIO_COPY_TO_CACHE constant? This constant? #define NETFS_FOLIO_COPY_TO_CACHE ((struct netfs_group *)0x356UL) /* Write to the cache only */ Yes. See explanation above. David