# include <linux/freezer.h>
#endif
+#if defined(LINUX_KEYRING_SUPPORT)
+# include <linux/rwsem.h>
+# include <linux/key.h>
+# if defined(HAVE_LINUX_KEY_TYPE_H)
+# include <linux/key-type.h>
+# endif
+# ifndef KEY_ALLOC_IN_QUOTA
+/* Before these flags were added in Linux commit v2.6.18-rc1~816,
+ * key_alloc just took a boolean not_in_quota */
+# define KEY_ALLOC_IN_QUOTA 0
+# define KEY_ALLOC_NOT_IN_QUOTA 1
+# endif
+#endif
+
#ifndef HAVE_LINUX_DO_SYNC_READ
static inline int
do_sync_read(struct file *fp, char *buf, size_t count, loff_t *offp) {
#define KALLOC_TYPE GFP_KERNEL
#endif
+#ifdef LINUX_KEYRING_SUPPORT
static inline struct key *
afs_linux_key_alloc(struct key_type *type, const char *desc, uid_t uid,
gid_t gid, key_perm_t perm, unsigned long flags)
{
-#if defined(KEY_ALLOC_NEEDS_STRUCT_TASK)
+# if defined(KEY_ALLOC_NEEDS_STRUCT_TASK)
return key_alloc(type, desc, uid, gid, current, perm, flags);
-#elif defined(KEY_ALLOC_NEEDS_CRED)
+# elif defined(KEY_ALLOC_NEEDS_CRED)
return key_alloc(type, desc, uid, gid, current_cred(), perm, flags);
-#else
+# else
return key_alloc(type, desc, uid, gid, perm, flags);
-#endif
+# endif
}
-#if defined(STRUCT_TASK_STRUCT_HAS_CRED)
+# if defined(STRUCT_TASK_STRUCT_HAS_CRED)
static inline struct key*
afs_linux_search_keyring(afs_ucred_t *cred, struct key_type *type)
{
return ERR_PTR(-ENOKEY);
}
+# else
+static inline struct key*
+afs_linux_search_keyring(afs_ucred_t *cred, struct key_type *type)
+{
+ return request_key(type, "_pag", NULL);
+}
+# endif /* STRUCT_TASK_STRUCT_HAS_CRED */
+#endif /* LINUX_KEYRING_SUPPORT */
+#ifdef STRUCT_TASK_STRUCT_HAS_CRED
static inline int
afs_linux_cred_is_current(afs_ucred_t *cred)
{
return (cred == current_cred());
}
-
#else
-static inline struct key*
-afs_linux_search_keyring(afs_ucred_t *cred, struct key_type *type)
-{
- return request_key(type, "_pag", NULL);
-}
-
static inline int
afs_linux_cred_is_current(afs_ucred_t *cred)
{
#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
return code;
}
+#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
+
+static inline void
+#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);
+ if (mnt)
+ *mnt = mntget(nd->path.mnt);
+ path_put(&nd->path);
+# else
+ *dpp = dget(path->dentry);
+ if (mnt)
+ *mnt = mntget(path->mnt);
+ path_put(path);
+# endif
+#else
+ *dpp = dget(nd->dentry);
+ if (mnt)
+ *mnt = mntget(nd->mnt);
+ path_release(nd);
+#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 */