X-Git-Url: http://git.openafs.org/?p=openafs.git;a=blobdiff_plain;f=src%2Fafs%2FLINUX%2Fosi_compat.h;h=d236081431d613999fc6222344785245329fb97a;hp=b94295c0635b665de9cf5bacd7e661039a1b7950;hb=02d82275c17284d04629282aa374bb39f511c989;hpb=f2e91cc3fe61956e7661eae9da82ddf746e63824 diff --git a/src/afs/LINUX/osi_compat.h b/src/afs/LINUX/osi_compat.h index b94295c..d236081 100644 --- a/src/afs/LINUX/osi_compat.h +++ b/src/afs/LINUX/osi_compat.h @@ -27,7 +27,35 @@ # endif #endif -#ifndef HAVE_LINUX_DO_SYNC_READ +#if defined(STRUCT_DENTRY_OPERATIONS_HAS_D_AUTOMOUNT) && !defined(DCACHE_NEED_AUTOMOUNT) +# define DCACHE_NEED_AUTOMOUNT DMANAGED_AUTOMOUNT +#endif + +#ifdef HAVE_LINUX_STRUCT_VFS_PATH +typedef struct vfs_path afs_linux_path_t; +#else +typedef struct path afs_linux_path_t; +#endif + +#if defined(STRUCT_DENTRY_HAS_D_U_D_ALIAS) +# define d_alias d_u.d_alias +#endif + +#if defined(STRUCT_FILE_HAS_F_PATH) +# if !defined(f_dentry) +# define f_dentry f_path.dentry +# endif +#endif + +#ifndef HAVE_LINUX_FILE_DENTRY +#define file_dentry(file) ((file)->f_dentry) +#endif + +#if defined(HAVE_LINUX_LOCKS_LOCK_FILE_WAIT) +# define flock_lock_file_wait locks_lock_file_wait +#endif + +#if !defined(HAVE_LINUX_DO_SYNC_READ) && !defined(STRUCT_FILE_OPERATIONS_HAS_READ_ITER) static inline int do_sync_read(struct file *fp, char *buf, size_t count, loff_t *offp) { return generic_file_read(fp, buf, count, offp); @@ -163,10 +191,12 @@ init_once_func(void * foo) { #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) +afs_linux_key_alloc(struct key_type *type, const char *desc, afs_kuid_t uid, + afs_kgid_t gid, key_perm_t perm, unsigned long flags) { -# if defined(KEY_ALLOC_NEEDS_STRUCT_TASK) +# if defined(KEY_ALLOC_BYPASS_RESTRICTION) + return key_alloc(type, desc, uid, gid, current_cred(), perm, flags, NULL); +# elif defined(KEY_ALLOC_NEEDS_STRUCT_TASK) return key_alloc(type, desc, uid, gid, current, perm, flags); # elif defined(KEY_ALLOC_NEEDS_CRED) return key_alloc(type, desc, uid, gid, current_cred(), perm, flags); @@ -176,15 +206,31 @@ afs_linux_key_alloc(struct key_type *type, const char *desc, uid_t uid, } # if defined(STRUCT_TASK_STRUCT_HAS_CRED) +static inline struct key * +afs_session_keyring(afs_ucred_t *cred) +{ +# if defined(STRUCT_CRED_HAS_SESSION_KEYRING) + return cred->session_keyring; +# else + return cred->tgcred->session_keyring; +# endif +} + static inline struct key* afs_linux_search_keyring(afs_ucred_t *cred, struct key_type *type) { key_ref_t key_ref; - if (cred->tgcred->session_keyring) { + if (afs_session_keyring(cred)) { +# if defined(KEYRING_SEARCH_TAKES_RECURSE) + key_ref = keyring_search( + make_key_ref(afs_session_keyring(cred), 1), + type, "_pag", 1); +# else key_ref = keyring_search( - make_key_ref(cred->tgcred->session_keyring, 1), + make_key_ref(afs_session_keyring(cred), 1), type, "_pag"); +# endif if (IS_ERR(key_ref)) return ERR_CAST(key_ref); @@ -200,6 +246,26 @@ afs_linux_search_keyring(afs_ucred_t *cred, struct key_type *type) return request_key(type, "_pag", NULL); } # endif /* STRUCT_TASK_STRUCT_HAS_CRED */ + +static_inline struct key * +afs_set_session_keyring(struct key *keyring) +{ + struct key *old; +#if defined(STRUCT_CRED_HAS_SESSION_KEYRING) + struct cred *new_creds; + old = current_session_keyring(); + new_creds = prepare_creds(); + rcu_assign_pointer(new_creds->session_keyring, keyring); + commit_creds(new_creds); +#else + spin_lock_irq(¤t->sighand->siglock); + old = task_session_keyring(current); + smp_wmb(); + task_session_keyring(current) = keyring; + spin_unlock_irq(¤t->sighand->siglock); +#endif + return old; +} #endif /* LINUX_KEYRING_SUPPORT */ #ifdef STRUCT_TASK_STRUCT_HAS_CRED @@ -220,7 +286,7 @@ afs_linux_cred_is_current(afs_ucred_t *cred) static inline loff_t page_offset(struct page *pp) { - return (((loff_t) pp->index) << PAGE_CACHE_SHIFT); + return (((loff_t) pp->index) << PAGE_SHIFT); } #endif @@ -279,22 +345,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 @@ -333,7 +417,11 @@ afs_get_dentry_from_fh(struct super_block *afs_cacheSBp, afs_dcache_id_t *ainode static inline int afs_get_fh_from_dentry(struct dentry *dp, afs_ufs_dcache_id_t *ainode, int *max_lenp) { if (dp->d_sb->s_export_op->encode_fh) +#if defined(EXPORT_OP_ENCODE_FH_TAKES_INODES) + return dp->d_sb->s_export_op->encode_fh(dp->d_inode, &ainode->raw[0], max_lenp, NULL); +#else return dp->d_sb->s_export_op->encode_fh(dp, &ainode->raw[0], max_lenp, 0); +#endif #if defined(NEW_EXPORT_OPS) /* If fs doesn't provide an encode_fh method, assume the default INO32 type */ *max_lenp = sizeof(struct fid)/4; @@ -369,7 +457,9 @@ afs_init_sb_export_ops(struct super_block *sb) { static inline void afs_linux_lock_inode(struct inode *ip) { -#ifdef STRUCT_INODE_HAS_I_MUTEX +#if defined(HAVE_LINUX_INODE_LOCK) + inode_lock(ip); +#elif defined(STRUCT_INODE_HAS_I_MUTEX) mutex_lock(&ip->i_mutex); #else down(&ip->i_sem); @@ -378,13 +468,42 @@ afs_linux_lock_inode(struct inode *ip) { static inline void afs_linux_unlock_inode(struct inode *ip) { -#ifdef STRUCT_INODE_HAS_I_MUTEX +#if defined(HAVE_LINUX_INODE_LOCK) + inode_unlock(ip); +#elif defined(STRUCT_INODE_HAS_I_MUTEX) mutex_unlock(&ip->i_mutex); #else up(&ip->i_sem); #endif } +/* Use these to lock or unlock an inode for processing + * its dentry aliases en masse. + */ +#if defined(HAVE_DCACHE_LOCK) +#define afs_d_alias_lock(ip) spin_lock(&dcache_lock) +#define afs_d_alias_unlock(ip) spin_unlock(&dcache_lock) +#else +#define afs_d_alias_lock(ip) spin_lock(&(ip)->i_lock) +#define afs_d_alias_unlock(ip) spin_unlock(&(ip)->i_lock) +#endif + + +/* Use this instead of dget for dentry operations + * that occur under a higher lock (e.g. alias processing). + * Requires that the higher lock (e.g. dcache_lock or + * inode->i_lock) is already held. + */ +static inline void +afs_linux_dget(struct dentry *dp) { +#if defined(HAVE_DCACHE_LOCK) + dget_locked(dp); +#else + dget(dp); +#endif +} + + static inline int afs_inode_setattr(struct osi_file *afile, struct iattr *newattrs) { @@ -410,7 +529,7 @@ afs_kern_path(char *aname, int flags, struct nameidata *nd) { } #else static inline int -afs_kern_path(char *aname, int flags, struct path *path) { +afs_kern_path(char *aname, int flags, afs_linux_path_t *path) { return kern_path(aname, flags, path); } #endif @@ -419,25 +538,183 @@ 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) { +afs_get_dentry_ref(afs_linux_path_t *path, struct vfsmount **mnt, struct dentry **dpp) { #endif -#if defined(STRUCT_NAMEIDATA_HAS_PATH) -# if defined(HAVE_LINUX_PATH_LOOKUP) +#if defined(HAVE_LINUX_PATH_LOOKUP) +# if defined(STRUCT_NAMEIDATA_HAS_PATH) *dpp = dget(nd->path.dentry); if (mnt) *mnt = mntget(nd->path.mnt); path_put(&nd->path); # else + *dpp = dget(nd->dentry); + if (mnt) + *mnt = mntget(nd->mnt); + path_release(nd); +# endif +#else *dpp = dget(path->dentry); if (mnt) *mnt = mntget(path->mnt); path_put(path); +#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 + +#if defined(STRUCT_TASK_STRUCT_HAS_CRED) +static inline struct file * +afs_dentry_open(struct dentry *dp, struct vfsmount *mnt, int flags, const struct cred *creds) { +#if defined(DENTRY_OPEN_TAKES_PATH) + afs_linux_path_t path; + struct file *filp; + path.mnt = mnt; + path.dentry = dp; + /* note that dentry_open will path_get for us */ + filp = dentry_open(&path, flags, creds); + return filp; +#else + return dentry_open(dget(dp), mntget(mnt), flags, creds); +#endif +} +#endif + +static inline int +afs_truncate(struct inode *inode, int len) +{ + int code; +#if defined(STRUCT_INODE_OPERATIONS_HAS_TRUNCATE) + code = vmtruncate(inode, len); +#else + code = inode_newsize_ok(inode, len); + if (!code) + truncate_setsize(inode, len); +#endif + return code; +} + +static inline struct proc_dir_entry * +afs_proc_create(char *name, umode_t mode, struct proc_dir_entry *parent, struct file_operations *fops) { +#if defined(HAVE_LINUX_PROC_CREATE) + return proc_create(name, mode, parent, fops); +#else + struct proc_dir_entry *entry; + entry = create_proc_entry(name, mode, parent); + if (entry) + entry->proc_fops = fops; + return entry; +#endif +} + +static inline int +afs_dentry_count(struct dentry *dp) +{ +#if defined(HAVE_LINUX_D_COUNT) + return d_count(dp); +#elif defined(D_COUNT_INT) + return dp->d_count; +#else + return atomic_read(&dp->d_count); +#endif +} + +static inline void +afs_maybe_shrink_dcache(struct dentry *dp) +{ +#if defined(HAVE_LINUX_D_COUNT) || defined(D_COUNT_INT) + spin_lock(&dp->d_lock); + if (afs_dentry_count(dp) > 1) { + spin_unlock(&dp->d_lock); + shrink_dcache_parent(dp); + } else + spin_unlock(&dp->d_lock); +#else + if (afs_dentry_count(dp) > 1) + shrink_dcache_parent(dp); +#endif +} + +static inline int +afs_d_invalidate(struct dentry *dp) +{ +#if defined(D_INVALIDATE_IS_VOID) + d_invalidate(dp); + return 0; +#else + return d_invalidate(dp); +#endif +} + +#if defined(HAVE_LINUX___VFS_WRITE) +# define AFS_FILE_NEEDS_SET_FS 1 +#elif defined(HAVE_LINUX_KERNEL_WRITE) +/* #undef AFS_FILE_NEEDS_SET_FS */ +#else +# define AFS_FILE_NEEDS_SET_FS 1 +#endif + +static inline int +afs_file_read(struct file *filp, char __user *buf, size_t len, loff_t *pos) +{ +#if defined(HAVE_LINUX___VFS_WRITE) + return __vfs_read(filp, buf, len, pos); +#elif defined(HAVE_LINUX_KERNEL_WRITE) +# if defined(KERNEL_READ_OFFSET_IS_LAST) + return kernel_read(filp, buf, len, pos); +# else + return kernel_read(filp, *pos, buf, len); # endif #else - *dpp = dget(nd->dentry); - if (mnt) - *mnt = mntget(nd->mnt); - path_release(nd); + return filp->f_op->read(filp, buf, len, pos); +#endif +} + +static inline int +afs_file_write(struct file *filp, char __user *buf, size_t len, loff_t *pos) +{ +#if defined(HAVE_LINUX___VFS_WRITE) + return __vfs_write(filp, buf, len, pos); +#elif defined(HAVE_LINUX_KERNEL_WRITE) +# if defined(KERNEL_READ_OFFSET_IS_LAST) + return kernel_write(filp, buf, len, pos); +# else + return kernel_write(filp, buf, len, *pos); +# endif +#else + return filp->f_op->write(filp, buf, len, pos); #endif }