1 /* Kernel compatibility routines
3 * This file contains definitions to provide compatibility between different
4 * versions of the Linux kernel. It is an ifdef maze, but the idea is that
5 * by concentrating the horror here, the rest of the tree may remaing a
9 #ifndef AFS_LINUX_OSI_COMPAT_H
10 #define AFS_LINUX_OSI_COMPAT_H
12 #if defined(HAVE_LINUX_FREEZER_H)
13 # include <linux/freezer.h>
16 #if defined(LINUX_KEYRING_SUPPORT)
17 # include <linux/rwsem.h>
18 # include <linux/key.h>
19 # if defined(HAVE_LINUX_KEY_TYPE_H)
20 # include <linux/key-type.h>
22 # ifndef KEY_ALLOC_IN_QUOTA
23 /* Before these flags were added in Linux commit v2.6.18-rc1~816,
24 * key_alloc just took a boolean not_in_quota */
25 # define KEY_ALLOC_IN_QUOTA 0
26 # define KEY_ALLOC_NOT_IN_QUOTA 1
30 #if defined(STRUCT_DENTRY_OPERATIONS_HAS_D_AUTOMOUNT) && !defined(DCACHE_NEED_AUTOMOUNT)
31 # define DCACHE_NEED_AUTOMOUNT DMANAGED_AUTOMOUNT
34 #ifdef HAVE_LINUX_STRUCT_VFS_PATH
35 typedef struct vfs_path afs_linux_path_t
;
37 typedef struct path afs_linux_path_t
;
40 #if defined(STRUCT_DENTRY_HAS_D_U_D_ALIAS)
41 # define d_alias d_u.d_alias
44 #if defined(STRUCT_FILE_HAS_F_PATH)
45 # if !defined(f_dentry)
46 # define f_dentry f_path.dentry
50 #ifndef HAVE_LINUX_FILE_DENTRY
51 #define file_dentry(file) ((file)->f_dentry)
54 #if defined(HAVE_LINUX_LOCKS_LOCK_FILE_WAIT)
55 # define flock_lock_file_wait locks_lock_file_wait
58 #if !defined(HAVE_LINUX_DO_SYNC_READ) && !defined(STRUCT_FILE_OPERATIONS_HAS_READ_ITER)
60 do_sync_read(struct file
*fp
, char *buf
, size_t count
, loff_t
*offp
) {
61 return generic_file_read(fp
, buf
, count
, offp
);
65 do_sync_write(struct file
*fp
, char *buf
, size_t count
, loff_t
*offp
) {
66 return generic_file_write(fp
, buf
, count
, offp
);
69 #endif /* DO_SYNC_READ */
72 afs_posix_lock_file(struct file
*fp
, struct file_lock
*flp
) {
73 #ifdef POSIX_LOCK_FILE_WAIT_ARG
74 return posix_lock_file(fp
, flp
, NULL
);
76 flp
->fl_flags
&=~ FL_SLEEP
;
77 return posix_lock_file(fp
, flp
);
82 afs_posix_test_lock(struct file
*fp
, struct file_lock
*flp
) {
83 #if defined(POSIX_TEST_LOCK_CONFLICT_ARG)
84 struct file_lock conflict
;
85 if (posix_test_lock(fp
, flp
, &conflict
)) {
86 locks_copy_lock(flp
, &conflict
);
87 flp
->fl_type
= F_UNLCK
;
89 #elif defined(POSIX_TEST_LOCK_RETURNS_CONFLICT)
90 struct file_lock
*conflict
;
91 conflict
= posix_test_lock(fp
, flp
);
93 locks_copy_lock(flp
, conflict
);
94 flp
->fl_type
= F_UNLCK
;
97 posix_test_lock(fp
, flp
);
101 #ifdef DCACHE_NFSFS_RENAMED
103 afs_linux_clear_nfsfs_renamed(struct dentry
*dp
) {
104 spin_lock(&dp
->d_lock
);
105 dp
->d_flags
&= ~DCACHE_NFSFS_RENAMED
;
106 spin_unlock(&dp
->d_lock
);
110 afs_linux_set_nfsfs_renamed(struct dentry
*dp
) {
111 spin_lock(&dp
->d_lock
);
112 dp
->d_flags
|= DCACHE_NFSFS_RENAMED
;
113 spin_unlock(&dp
->d_lock
);
117 afs_linux_nfsfs_renamed(struct dentry
*dp
) {
118 return dp
->d_flags
& DCACHE_NFSFS_RENAMED
;
122 static inline void afs_linux_clear_nfsfs_renamed(void) { return; }
123 static inline void afs_linux_set_nfsfs_renamed(void) { return; }
126 #ifndef HAVE_LINUX_HLIST_UNHASHED
128 hlist_unhashed(const struct hlist_node
*h
) {
129 return (!h
->pprev
== NULL
);
133 #if defined(WRITEPAGE_ACTIVATE)
134 #define AOP_WRITEPAGE_ACTIVATE WRITEPAGE_ACTIVATE
137 #if defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_WRITE_BEGIN) && !defined(HAVE_LINUX_GRAB_CACHE_PAGE_WRITE_BEGIN)
138 static inline struct page
*
139 grab_cache_page_write_begin(struct address_space
*mapping
, pgoff_t index
,
140 unsigned int flags
) {
141 return __grab_cache_page(mapping
, index
);
145 #if defined(HAVE_KMEM_CACHE_T)
146 #define afs_kmem_cache_t kmem_cache_t
148 #define afs_kmem_cache_t struct kmem_cache
151 extern void init_once(void *);
152 #if defined(HAVE_KMEM_CACHE_T)
154 init_once_func(void * foo
, kmem_cache_t
* cachep
, unsigned long flags
) {
155 #if defined(SLAB_CTOR_VERIFY)
156 if ((flags
& (SLAB_CTOR_VERIFY
|SLAB_CTOR_CONSTRUCTOR
)) ==
157 SLAB_CTOR_CONSTRUCTOR
)
161 #elif defined(KMEM_CACHE_INIT)
163 init_once_func(struct kmem_cache
* cachep
, void * foo
) {
166 #elif !defined(KMEM_CACHE_CTOR_TAKES_VOID)
168 init_once_func(void * foo
, struct kmem_cache
* cachep
, unsigned long flags
) {
169 #if defined(SLAB_CTOR_VERIFY)
170 if ((flags
& (SLAB_CTOR_VERIFY
|SLAB_CTOR_CONSTRUCTOR
)) ==
171 SLAB_CTOR_CONSTRUCTOR
)
177 init_once_func(void * foo
) {
182 #ifndef SLAB_RECLAIM_ACCOUNT
183 #define SLAB_RECLAIM_ACCOUNT 0
186 #if defined(SLAB_KERNEL)
187 #define KALLOC_TYPE SLAB_KERNEL
189 #define KALLOC_TYPE GFP_KERNEL
192 #ifdef LINUX_KEYRING_SUPPORT
193 static inline struct key
*
194 afs_linux_key_alloc(struct key_type
*type
, const char *desc
, afs_kuid_t uid
,
195 afs_kgid_t gid
, key_perm_t perm
, unsigned long flags
)
197 # if defined(KEY_ALLOC_BYPASS_RESTRICTION)
198 return key_alloc(type
, desc
, uid
, gid
, current_cred(), perm
, flags
, NULL
);
199 # elif defined(KEY_ALLOC_NEEDS_STRUCT_TASK)
200 return key_alloc(type
, desc
, uid
, gid
, current
, perm
, flags
);
201 # elif defined(KEY_ALLOC_NEEDS_CRED)
202 return key_alloc(type
, desc
, uid
, gid
, current_cred(), perm
, flags
);
204 return key_alloc(type
, desc
, uid
, gid
, perm
, flags
);
208 # if defined(STRUCT_TASK_STRUCT_HAS_CRED)
209 static inline struct key
*
210 afs_session_keyring(afs_ucred_t
*cred
)
212 # if defined(STRUCT_CRED_HAS_SESSION_KEYRING)
213 return cred
->session_keyring
;
215 return cred
->tgcred
->session_keyring
;
219 static inline struct key
*
220 afs_linux_search_keyring(afs_ucred_t
*cred
, struct key_type
*type
)
224 if (afs_session_keyring(cred
)) {
225 # if defined(KEYRING_SEARCH_TAKES_RECURSE)
226 key_ref
= keyring_search(
227 make_key_ref(afs_session_keyring(cred
), 1),
230 key_ref
= keyring_search(
231 make_key_ref(afs_session_keyring(cred
), 1),
235 return ERR_CAST(key_ref
);
237 return key_ref_to_ptr(key_ref
);
240 return ERR_PTR(-ENOKEY
);
243 static inline struct key
*
244 afs_linux_search_keyring(afs_ucred_t
*cred
, struct key_type
*type
)
246 return request_key(type
, "_pag", NULL
);
248 # endif /* STRUCT_TASK_STRUCT_HAS_CRED */
250 static_inline
struct key
*
251 afs_set_session_keyring(struct key
*keyring
)
254 #if defined(STRUCT_CRED_HAS_SESSION_KEYRING)
255 struct cred
*new_creds
;
256 old
= current_session_keyring();
257 new_creds
= prepare_creds();
258 rcu_assign_pointer(new_creds
->session_keyring
, keyring
);
259 commit_creds(new_creds
);
261 spin_lock_irq(¤t
->sighand
->siglock
);
262 old
= task_session_keyring(current
);
264 task_session_keyring(current
) = keyring
;
265 spin_unlock_irq(¤t
->sighand
->siglock
);
269 #endif /* LINUX_KEYRING_SUPPORT */
271 #ifdef STRUCT_TASK_STRUCT_HAS_CRED
273 afs_linux_cred_is_current(afs_ucred_t
*cred
)
275 return (cred
== current_cred());
279 afs_linux_cred_is_current(afs_ucred_t
*cred
)
285 #ifndef HAVE_LINUX_PAGE_OFFSET
287 page_offset(struct page
*pp
)
289 return (((loff_t
) pp
->index
) << PAGE_SHIFT
);
293 #ifndef HAVE_LINUX_ZERO_USER_SEGMENTS
295 zero_user_segments(struct page
*pp
, unsigned int from1
, unsigned int to1
,
296 unsigned int from2
, unsigned int to2
)
298 void *base
= kmap_atomic(pp
, KM_USER0
);
301 memset(base
+ from1
, 0, to1
- from1
);
304 memset(base
+ from2
, 0, to2
- from2
);
306 flush_dcache_page(pp
);
307 kunmap_atomic(base
, KM_USER0
);
311 zero_user_segment(struct page
*pp
, unsigned int from1
, unsigned int to1
)
313 zero_user_segments(pp
, from1
, to1
, 0, 0);
317 #ifndef HAVE_LINUX_KERNEL_SETSOCKOPT
318 /* Available from 2.6.19 */
321 kernel_setsockopt(struct socket
*sockp
, int level
, int name
, char *val
,
323 mm_segment_t old_fs
= get_fs();
327 ret
= sockp
->ops
->setsockopt(sockp
, level
, name
, val
, len
);
334 kernel_getsockopt(struct socket
*sockp
, int level
, int name
, char *val
,
336 mm_segment_t old_fs
= get_fs();
340 ret
= sockp
->ops
->getsockopt(sockp
, level
, name
, val
, len
);
347 #ifdef HAVE_TRY_TO_FREEZE
349 afs_try_to_freeze(void) {
350 # ifdef LINUX_REFRIGERATOR_TAKES_PF_FREEZE
351 return try_to_freeze(PF_FREEZE
);
353 return try_to_freeze();
358 afs_try_to_freeze(void) {
360 if (current
->flags
& PF_FREEZE
) {
361 refrigerator(PF_FREEZE
);
369 /* The commit which changed refrigerator so that it takes no arguments
370 * also added freezing(), so if LINUX_REFRIGERATOR_TAKES_PF_FREEZE is
371 * true, the kernel doesn't have a freezing() function.
373 #ifdef LINUX_REFRIGERATOR_TAKES_PF_FREEZE
375 freezing(struct task_struct
*p
)
378 return p
->flags
& PF_FREEZE
;
385 #if !defined(HAVE_LINUX_PAGECHECKED)
386 # if defined(HAVE_LINUX_PAGEFSMISC)
387 # include <linux/page-flags.h>
389 # define PageChecked(p) PageFsMisc((p))
390 # define SetPageChecked(p) SetPageFsMisc((p))
391 # define ClearPageChecked(p) ClearPageFsMisc((p))
396 #if !defined(NEW_EXPORT_OPS)
397 extern struct export_operations export_op_default
;
400 static inline struct dentry
*
401 afs_get_dentry_from_fh(struct super_block
*afs_cacheSBp
, afs_dcache_id_t
*ainode
,
402 int cache_fh_len
, int cache_fh_type
,
403 int (*afs_fh_acceptable
)(void *, struct dentry
*)) {
404 #if defined(NEW_EXPORT_OPS)
405 return afs_cacheSBp
->s_export_op
->fh_to_dentry(afs_cacheSBp
, &ainode
->ufs
.fh
,
406 cache_fh_len
, cache_fh_type
);
408 if (afs_cacheSBp
->s_export_op
&& afs_cacheSBp
->s_export_op
->decode_fh
)
409 return afs_cacheSBp
->s_export_op
->decode_fh(afs_cacheSBp
, ainode
->ufs
.raw
,
410 cache_fh_len
, cache_fh_type
, afs_fh_acceptable
, NULL
);
412 return export_op_default
.decode_fh(afs_cacheSBp
, ainode
->ufs
.raw
,
413 cache_fh_len
, cache_fh_type
, afs_fh_acceptable
, NULL
);
418 afs_get_fh_from_dentry(struct dentry
*dp
, afs_ufs_dcache_id_t
*ainode
, int *max_lenp
) {
419 if (dp
->d_sb
->s_export_op
->encode_fh
)
420 #if defined(EXPORT_OP_ENCODE_FH_TAKES_INODES)
421 return dp
->d_sb
->s_export_op
->encode_fh(dp
->d_inode
, &ainode
->raw
[0], max_lenp
, NULL
);
423 return dp
->d_sb
->s_export_op
->encode_fh(dp
, &ainode
->raw
[0], max_lenp
, 0);
425 #if defined(NEW_EXPORT_OPS)
426 /* If fs doesn't provide an encode_fh method, assume the default INO32 type */
427 *max_lenp
= sizeof(struct fid
)/4;
428 ainode
->fh
.i32
.ino
= dp
->d_inode
->i_ino
;
429 ainode
->fh
.i32
.gen
= dp
->d_inode
->i_generation
;
430 return FILEID_INO32_GEN
;
432 /* or call the default encoding function for the old API */
433 return export_op_default
.encode_fh(dp
, &ainode
->raw
[0], max_lenp
, 0);
438 afs_init_sb_export_ops(struct super_block
*sb
) {
439 #if !defined(NEW_EXPORT_OPS)
441 * decode_fh will call this function. If not defined for this FS, make
442 * sure it points to the default
444 if (!sb
->s_export_op
->find_exported_dentry
) {
445 /* Some kernels (at least 2.6.9) do not prototype find_exported_dentry,
446 * even though it is exported, so prototype it ourselves. Newer
447 * kernels do prototype it, but as long as our protoype matches the
448 * real one (the signature never changed before NEW_EXPORT_OPS came
449 * into play), there should be no problems. */
450 extern struct dentry
* find_exported_dentry(struct super_block
*sb
, void *obj
, void *parent
,
451 int (*acceptable
)(void *context
, struct dentry
*de
),
453 sb
->s_export_op
->find_exported_dentry
= find_exported_dentry
;
459 afs_linux_lock_inode(struct inode
*ip
) {
460 #if defined(HAVE_LINUX_INODE_LOCK)
462 #elif defined(STRUCT_INODE_HAS_I_MUTEX)
463 mutex_lock(&ip
->i_mutex
);
470 afs_linux_unlock_inode(struct inode
*ip
) {
471 #if defined(HAVE_LINUX_INODE_LOCK)
473 #elif defined(STRUCT_INODE_HAS_I_MUTEX)
474 mutex_unlock(&ip
->i_mutex
);
480 /* Use these to lock or unlock an inode for processing
481 * its dentry aliases en masse.
483 #if defined(HAVE_DCACHE_LOCK)
484 #define afs_d_alias_lock(ip) spin_lock(&dcache_lock)
485 #define afs_d_alias_unlock(ip) spin_unlock(&dcache_lock)
487 #define afs_d_alias_lock(ip) spin_lock(&(ip)->i_lock)
488 #define afs_d_alias_unlock(ip) spin_unlock(&(ip)->i_lock)
492 /* Use this instead of dget for dentry operations
493 * that occur under a higher lock (e.g. alias processing).
494 * Requires that the higher lock (e.g. dcache_lock or
495 * inode->i_lock) is already held.
498 afs_linux_dget(struct dentry
*dp
) {
499 #if defined(HAVE_DCACHE_LOCK)
508 afs_inode_setattr(struct osi_file
*afile
, struct iattr
*newattrs
) {
511 struct inode
*inode
= OSIFILE_INODE(afile
);
512 #if !defined(HAVE_LINUX_INODE_SETATTR)
513 code
= inode
->i_op
->setattr(afile
->filp
->f_dentry
, newattrs
);
514 #elif defined(INODE_SETATTR_NOT_VOID)
515 if (inode
->i_op
&& inode
->i_op
->setattr
)
516 code
= inode
->i_op
->setattr(afile
->filp
->f_dentry
, newattrs
);
518 code
= inode_setattr(inode
, newattrs
);
520 inode_setattr(inode
, newattrs
);
525 #if defined(HAVE_LINUX_PATH_LOOKUP)
527 afs_kern_path(char *aname
, int flags
, struct nameidata
*nd
) {
528 return path_lookup(aname
, flags
, nd
);
532 afs_kern_path(char *aname
, int flags
, afs_linux_path_t
*path
) {
533 return kern_path(aname
, flags
, path
);
538 #if defined(HAVE_LINUX_PATH_LOOKUP)
539 afs_get_dentry_ref(struct nameidata
*nd
, struct vfsmount
**mnt
, struct dentry
**dpp
) {
541 afs_get_dentry_ref(afs_linux_path_t
*path
, struct vfsmount
**mnt
, struct dentry
**dpp
) {
543 #if defined(HAVE_LINUX_PATH_LOOKUP)
544 # if defined(STRUCT_NAMEIDATA_HAS_PATH)
545 *dpp
= dget(nd
->path
.dentry
);
547 *mnt
= mntget(nd
->path
.mnt
);
550 *dpp
= dget(nd
->dentry
);
552 *mnt
= mntget(nd
->mnt
);
556 *dpp
= dget(path
->dentry
);
558 *mnt
= mntget(path
->mnt
);
563 /* wait_event_freezable appeared with 2.6.24 */
565 /* These implement the original AFS wait behaviour, with respect to the
566 * refrigerator, rather than the behaviour of the current wait_event_freezable
570 #ifndef wait_event_freezable
571 # define wait_event_freezable(waitqueue, condition) \
575 _ret = wait_event_interruptible(waitqueue, \
576 (condition) || freezing(current)); \
577 if (_ret && !freezing(current)) \
579 else if (!(condition)) \
581 } while (afs_try_to_freeze()); \
585 # define wait_event_freezable_timeout(waitqueue, condition, timeout) \
589 _ret = wait_event_interruptible_timeout(waitqueue, \
591 freezing(current)), \
593 } while (afs_try_to_freeze()); \
598 #if defined(STRUCT_TASK_STRUCT_HAS_CRED)
599 static inline struct file
*
600 afs_dentry_open(struct dentry
*dp
, struct vfsmount
*mnt
, int flags
, const struct cred
*creds
) {
601 #if defined(DENTRY_OPEN_TAKES_PATH)
602 afs_linux_path_t path
;
606 /* note that dentry_open will path_get for us */
607 filp
= dentry_open(&path
, flags
, creds
);
610 return dentry_open(dget(dp
), mntget(mnt
), flags
, creds
);
616 afs_truncate(struct inode
*inode
, int len
)
619 #if defined(STRUCT_INODE_OPERATIONS_HAS_TRUNCATE)
620 code
= vmtruncate(inode
, len
);
622 code
= inode_newsize_ok(inode
, len
);
624 truncate_setsize(inode
, len
);
629 static inline struct proc_dir_entry
*
630 afs_proc_create(char *name
, umode_t mode
, struct proc_dir_entry
*parent
, struct file_operations
*fops
) {
631 #if defined(HAVE_LINUX_PROC_CREATE)
632 return proc_create(name
, mode
, parent
, fops
);
634 struct proc_dir_entry
*entry
;
635 entry
= create_proc_entry(name
, mode
, parent
);
637 entry
->proc_fops
= fops
;
643 afs_dentry_count(struct dentry
*dp
)
645 #if defined(HAVE_LINUX_D_COUNT)
647 #elif defined(D_COUNT_INT)
650 return atomic_read(&dp
->d_count
);
655 afs_maybe_shrink_dcache(struct dentry
*dp
)
657 #if defined(HAVE_LINUX_D_COUNT) || defined(D_COUNT_INT)
658 spin_lock(&dp
->d_lock
);
659 if (afs_dentry_count(dp
) > 1) {
660 spin_unlock(&dp
->d_lock
);
661 shrink_dcache_parent(dp
);
663 spin_unlock(&dp
->d_lock
);
665 if (afs_dentry_count(dp
) > 1)
666 shrink_dcache_parent(dp
);
671 afs_d_invalidate(struct dentry
*dp
)
673 #if defined(D_INVALIDATE_IS_VOID)
677 return d_invalidate(dp
);
681 #if defined(HAVE_LINUX___VFS_WRITE)
682 # define AFS_FILE_NEEDS_SET_FS 1
683 #elif defined(HAVE_LINUX_KERNEL_WRITE)
684 /* #undef AFS_FILE_NEEDS_SET_FS */
686 # define AFS_FILE_NEEDS_SET_FS 1
690 afs_file_read(struct file
*filp
, char __user
*buf
, size_t len
, loff_t
*pos
)
692 #if defined(HAVE_LINUX___VFS_WRITE)
693 return __vfs_read(filp
, buf
, len
, pos
);
694 #elif defined(HAVE_LINUX_KERNEL_WRITE)
695 # if defined(KERNEL_READ_OFFSET_IS_LAST)
696 return kernel_read(filp
, buf
, len
, pos
);
698 return kernel_read(filp
, *pos
, buf
, len
);
701 return filp
->f_op
->read(filp
, buf
, len
, pos
);
706 afs_file_write(struct file
*filp
, char __user
*buf
, size_t len
, loff_t
*pos
)
708 #if defined(HAVE_LINUX___VFS_WRITE)
709 return __vfs_write(filp
, buf
, len
, pos
);
710 #elif defined(HAVE_LINUX_KERNEL_WRITE)
711 # if defined(KERNEL_READ_OFFSET_IS_LAST)
712 return kernel_write(filp
, buf
, len
, pos
);
714 return kernel_write(filp
, buf
, len
, *pos
);
717 return filp
->f_op
->write(filp
, buf
, len
, pos
);
721 #endif /* AFS_LINUX_OSI_COMPAT_H */