#ifdef STRUCT_FILE_OPERATIONS_HAS_READ_ITER
.read_iter = afs_linux_read_iter,
.write_iter = afs_linux_write_iter,
+# if !defined(HAVE_LINUX___VFS_READ)
.read = new_sync_read,
.write = new_sync_write,
+# endif
#elif defined(HAVE_LINUX_GENERIC_FILE_AIO_READ)
.aio_read = afs_linux_aio_read,
.aio_write = afs_linux_aio_write,
{
struct dentry *target;
- /* avoid symlink resolution limits when resolving; we cannot contribute to
- * an infinite symlink loop */
+ /*
+ * Avoid symlink resolution limits when resolving; we cannot contribute to
+ * an infinite symlink loop.
+ *
+ * On newer kernels the field has moved to the private nameidata structure
+ * so we can't adjust it here. This may cause ELOOP when using a path with
+ * 40 or more directories that are not already in the dentry cache.
+ */
+#if defined(STRUCT_TASK_STRUCT_HAS_TOTAL_LINK_COUNT)
current->total_link_count--;
+#endif
target = canonical_dentry(path->dentry->d_inode);
* locked */
static inline int
afs_linux_prepare_writeback(struct vcache *avc) {
- if (avc->f.states & CPageWrite) {
- return AOP_WRITEPAGE_ACTIVATE;
+ pid_t pid;
+ struct pagewriter *pw;
+
+ pid = MyPidxx2Pid(MyPidxx);
+ /* Prevent recursion into the writeback code */
+ spin_lock(&avc->pagewriter_lock);
+ list_for_each_entry(pw, &avc->pagewriters, link) {
+ if (pw->writer == pid) {
+ spin_unlock(&avc->pagewriter_lock);
+ return AOP_WRITEPAGE_ACTIVATE;
+ }
}
- avc->f.states |= CPageWrite;
+ spin_unlock(&avc->pagewriter_lock);
+
+ /* Add ourselves to writer list */
+ pw = osi_Alloc(sizeof(struct pagewriter));
+ pw->writer = pid;
+ spin_lock(&avc->pagewriter_lock);
+ list_add_tail(&pw->link, &avc->pagewriters);
+ spin_unlock(&avc->pagewriter_lock);
+
return 0;
}
static inline void
afs_linux_complete_writeback(struct vcache *avc) {
- avc->f.states &= ~CPageWrite;
+ struct pagewriter *pw, *store;
+ pid_t pid;
+ struct list_head tofree;
+
+ INIT_LIST_HEAD(&tofree);
+ pid = MyPidxx2Pid(MyPidxx);
+ /* Remove ourselves from writer list */
+ spin_lock(&avc->pagewriter_lock);
+ list_for_each_entry_safe(pw, store, &avc->pagewriters, link) {
+ if (pw->writer == pid) {
+ list_del(&pw->link);
+ /* osi_Free may sleep so we need to defer it */
+ list_add_tail(&pw->link, &tofree);
+ }
+ }
+ spin_unlock(&avc->pagewriter_lock);
+ list_for_each_entry_safe(pw, store, &tofree, link) {
+ list_del(&pw->link);
+ osi_Free(pw, sizeof(struct pagewriter));
+ }
}
/* Writeback a given page syncronously. Called with no AFS locks held */