Linux CM: Update wait code
[openafs.git] / src / afs / LINUX / osi_compat.h
index e4f0735..6213734 100644 (file)
@@ -279,22 +279,40 @@ kernel_getsockopt(struct socket *sockp, int level, int name, char *val,
 #endif
 
 #ifdef HAVE_TRY_TO_FREEZE
-static inline void
+static inline int
 afs_try_to_freeze(void) {
 # ifdef LINUX_REFRIGERATOR_TAKES_PF_FREEZE
-    try_to_freeze(PF_FREEZE);
+    return try_to_freeze(PF_FREEZE);
 # else
-    try_to_freeze();
+    return try_to_freeze();
 # endif
 }
 #else
-static inline void
+static inline int
 afs_try_to_freeze(void) {
 # ifdef CONFIG_PM
     if (current->flags & PF_FREEZE) {
        refrigerator(PF_FREEZE);
+       return 1;
     }
 # endif
+    return 0;
+}
+#endif
+
+/* The commit which changed refrigerator so that it takes no arguments
+ * also added freezing(), so if LINUX_REFRIGERATOR_TAKES_PF_FREEZE is
+ * true, the kernel doesn't have a freezing() function.
+ */
+#ifdef LINUX_REFRIGERATOR_TAKES_PF_FREEZE
+static inline int
+freezing(struct task_struct *p)
+{
+# ifdef CONFIG_PM
+    return p->flags & PF_FREEZE;
+# else
+    return 0;
+# endif
 }
 #endif
 
@@ -403,17 +421,24 @@ afs_inode_setattr(struct osi_file *afile, struct iattr *newattrs) {
     return code;
 }
 
-static inline int
-afs_kern_path(char *aname, int flags, struct nameidata *nd, struct path *path) {
 #if defined(HAVE_LINUX_PATH_LOOKUP)
+static inline int
+afs_kern_path(char *aname, int flags, struct nameidata *nd) {
     return path_lookup(aname, flags, nd);
+}
 #else
+static inline int
+afs_kern_path(char *aname, int flags, struct path *path) {
     return kern_path(aname, flags, path);
-#endif
 }
+#endif
 
 static inline void
-afs_get_dentry_ref(struct nameidata *nd, struct path *path, struct vfsmount **mnt, struct dentry **dpp) {
+#if defined(HAVE_LINUX_PATH_LOOKUP)
+afs_get_dentry_ref(struct nameidata *nd, struct vfsmount **mnt, struct dentry **dpp) {
+#else
+afs_get_dentry_ref(struct path *path, struct vfsmount **mnt, struct dentry **dpp) {
+#endif
 #if defined(STRUCT_NAMEIDATA_HAS_PATH)
 # if defined(HAVE_LINUX_PATH_LOOKUP)
     *dpp = dget(nd->path.dentry);
@@ -434,4 +459,39 @@ afs_get_dentry_ref(struct nameidata *nd, struct path *path, struct vfsmount **mn
 #endif
 }
 
+/* wait_event_freezable appeared with 2.6.24 */
+
+/* These implement the original AFS wait behaviour, with respect to the
+ * refrigerator, rather than the behaviour of the current wait_event_freezable
+ * implementation.
+ */
+
+#ifndef wait_event_freezable
+# define wait_event_freezable(waitqueue, condition)                            \
+({                                                                             \
+    int _ret;                                                                  \
+    do {                                                                       \
+       _ret = wait_event_interruptible(waitqueue,                              \
+                                       (condition) || freezing(current));      \
+       if (_ret && !freezing(current))                                 \
+           break;                                                              \
+       else if (!(condition))                                                  \
+           _ret = -EINTR;                                                      \
+    } while (afs_try_to_freeze());                                             \
+    _ret;                                                                      \
+})
+
+# define wait_event_freezable_timeout(waitqueue, condition, timeout)           \
+({                                                                             \
+     int _ret;                                                                 \
+     do {                                                                      \
+       _ret = wait_event_interruptible_timeout(waitqueue,                      \
+                                               (condition ||                   \
+                                                freezing(current)),            \
+                                               timeout);                       \
+     } while (afs_try_to_freeze());                                            \
+     _ret;                                                                     \
+})
+#endif
+
 #endif /* AFS_LINUX_OSI_COMPAT_H */