OpenAFS
OpenAFS distributed network file system
|
00001 /* Kernel compatibility routines 00002 * 00003 * This file contains definitions to provide compatibility between different 00004 * versions of the Linux kernel. It is an ifdef maze, but the idea is that 00005 * by concentrating the horror here, the rest of the tree may remaing a 00006 * little cleaner... 00007 */ 00008 00009 #ifndef AFS_LINUX_OSI_COMPAT_H 00010 #define AFS_LINUX_OSI_COMPAT_H 00011 00012 #if defined(HAVE_LINUX_FREEZER_H) 00013 # include <linux/freezer.h> 00014 #endif 00015 00016 #if defined(LINUX_KEYRING_SUPPORT) 00017 # include <linux/rwsem.h> 00018 # include <linux/key.h> 00019 # if defined(HAVE_LINUX_KEY_TYPE_H) 00020 # include <linux/key-type.h> 00021 # endif 00022 # ifndef KEY_ALLOC_IN_QUOTA 00023 /* Before these flags were added in Linux commit v2.6.18-rc1~816, 00024 * key_alloc just took a boolean not_in_quota */ 00025 # define KEY_ALLOC_IN_QUOTA 0 00026 # define KEY_ALLOC_NOT_IN_QUOTA 1 00027 # endif 00028 #endif 00029 00030 #if defined(STRUCT_DENTRY_OPERATIONS_HAS_D_AUTOMOUNT) && !defined(DCACHE_NEED_AUTOMOUNT) 00031 # define DCACHE_NEED_AUTOMOUNT DMANAGED_AUTOMOUNT 00032 #endif 00033 00034 #ifdef HAVE_LINUX_STRUCT_VFS_PATH 00035 typedef struct vfs_path afs_linux_path_t; 00036 #else 00037 typedef struct path afs_linux_path_t; 00038 #endif 00039 00040 #ifndef HAVE_LINUX_DO_SYNC_READ 00041 static inline int 00042 do_sync_read(struct file *fp, char *buf, size_t count, loff_t *offp) { 00043 return generic_file_read(fp, buf, count, offp); 00044 } 00045 00046 static inline int 00047 do_sync_write(struct file *fp, char *buf, size_t count, loff_t *offp) { 00048 return generic_file_write(fp, buf, count, offp); 00049 } 00050 00051 #endif /* DO_SYNC_READ */ 00052 00053 static inline int 00054 afs_posix_lock_file(struct file *fp, struct file_lock *flp) { 00055 #ifdef POSIX_LOCK_FILE_WAIT_ARG 00056 return posix_lock_file(fp, flp, NULL); 00057 #else 00058 flp->fl_flags &=~ FL_SLEEP; 00059 return posix_lock_file(fp, flp); 00060 #endif 00061 } 00062 00063 static inline void 00064 afs_posix_test_lock(struct file *fp, struct file_lock *flp) { 00065 #if defined(POSIX_TEST_LOCK_CONFLICT_ARG) 00066 struct file_lock conflict; 00067 if (posix_test_lock(fp, flp, &conflict)) { 00068 locks_copy_lock(flp, &conflict); 00069 flp->fl_type = F_UNLCK; 00070 } 00071 #elif defined(POSIX_TEST_LOCK_RETURNS_CONFLICT) 00072 struct file_lock *conflict; 00073 conflict = posix_test_lock(fp, flp); 00074 if (conflict) { 00075 locks_copy_lock(flp, conflict); 00076 flp->fl_type = F_UNLCK; 00077 } 00078 #else 00079 posix_test_lock(fp, flp); 00080 #endif 00081 } 00082 00083 #ifdef DCACHE_NFSFS_RENAMED 00084 static inline void 00085 afs_linux_clear_nfsfs_renamed(struct dentry *dp) { 00086 spin_lock(&dp->d_lock); 00087 dp->d_flags &= ~DCACHE_NFSFS_RENAMED; 00088 spin_unlock(&dp->d_lock); 00089 } 00090 00091 static inline void 00092 afs_linux_set_nfsfs_renamed(struct dentry *dp) { 00093 spin_lock(&dp->d_lock); 00094 dp->d_flags |= DCACHE_NFSFS_RENAMED; 00095 spin_unlock(&dp->d_lock); 00096 } 00097 00098 static inline int 00099 afs_linux_nfsfs_renamed(struct dentry *dp) { 00100 return dp->d_flags & DCACHE_NFSFS_RENAMED; 00101 } 00102 00103 #else 00104 static inline void afs_linux_clear_nfsfs_renamed(void) { return; } 00105 static inline void afs_linux_set_nfsfs_renamed(void) { return; } 00106 #endif 00107 00108 #ifndef HAVE_LINUX_HLIST_UNHASHED 00109 static void 00110 hlist_unhashed(const struct hlist_node *h) { 00111 return (!h->pprev == NULL); 00112 } 00113 #endif 00114 00115 #if defined(WRITEPAGE_ACTIVATE) 00116 #define AOP_WRITEPAGE_ACTIVATE WRITEPAGE_ACTIVATE 00117 #endif 00118 00119 #if defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_WRITE_BEGIN) && !defined(HAVE_LINUX_GRAB_CACHE_PAGE_WRITE_BEGIN) 00120 static inline struct page * 00121 grab_cache_page_write_begin(struct address_space *mapping, pgoff_t index, 00122 unsigned int flags) { 00123 return __grab_cache_page(mapping, index); 00124 } 00125 #endif 00126 00127 #if defined(HAVE_KMEM_CACHE_T) 00128 #define afs_kmem_cache_t kmem_cache_t 00129 #else 00130 #define afs_kmem_cache_t struct kmem_cache 00131 #endif 00132 00133 extern void init_once(void *); 00134 #if defined(HAVE_KMEM_CACHE_T) 00135 static inline void 00136 init_once_func(void * foo, kmem_cache_t * cachep, unsigned long flags) { 00137 #if defined(SLAB_CTOR_VERIFY) 00138 if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == 00139 SLAB_CTOR_CONSTRUCTOR) 00140 #endif 00141 init_once(foo); 00142 } 00143 #elif defined(KMEM_CACHE_INIT) 00144 static inline void 00145 init_once_func(struct kmem_cache * cachep, void * foo) { 00146 init_once(foo); 00147 } 00148 #elif !defined(KMEM_CACHE_CTOR_TAKES_VOID) 00149 static inline void 00150 init_once_func(void * foo, struct kmem_cache * cachep, unsigned long flags) { 00151 #if defined(SLAB_CTOR_VERIFY) 00152 if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == 00153 SLAB_CTOR_CONSTRUCTOR) 00154 #endif 00155 init_once(foo); 00156 } 00157 #else 00158 static inline void 00159 init_once_func(void * foo) { 00160 init_once(foo); 00161 } 00162 #endif 00163 00164 #ifndef SLAB_RECLAIM_ACCOUNT 00165 #define SLAB_RECLAIM_ACCOUNT 0 00166 #endif 00167 00168 #if defined(SLAB_KERNEL) 00169 #define KALLOC_TYPE SLAB_KERNEL 00170 #else 00171 #define KALLOC_TYPE GFP_KERNEL 00172 #endif 00173 00174 #ifdef LINUX_KEYRING_SUPPORT 00175 static inline struct key * 00176 afs_linux_key_alloc(struct key_type *type, const char *desc, uid_t uid, 00177 gid_t gid, key_perm_t perm, unsigned long flags) 00178 { 00179 # if defined(KEY_ALLOC_NEEDS_STRUCT_TASK) 00180 return key_alloc(type, desc, uid, gid, current, perm, flags); 00181 # elif defined(KEY_ALLOC_NEEDS_CRED) 00182 return key_alloc(type, desc, uid, gid, current_cred(), perm, flags); 00183 # else 00184 return key_alloc(type, desc, uid, gid, perm, flags); 00185 # endif 00186 } 00187 00188 # if defined(STRUCT_TASK_STRUCT_HAS_CRED) 00189 static inline struct key* 00190 afs_linux_search_keyring(afs_ucred_t *cred, struct key_type *type) 00191 { 00192 key_ref_t key_ref; 00193 00194 if (cred->tgcred->session_keyring) { 00195 key_ref = keyring_search( 00196 make_key_ref(cred->tgcred->session_keyring, 1), 00197 type, "_pag"); 00198 if (IS_ERR(key_ref)) 00199 return ERR_CAST(key_ref); 00200 00201 return key_ref_to_ptr(key_ref); 00202 } 00203 00204 return ERR_PTR(-ENOKEY); 00205 } 00206 # else 00207 static inline struct key* 00208 afs_linux_search_keyring(afs_ucred_t *cred, struct key_type *type) 00209 { 00210 return request_key(type, "_pag", NULL); 00211 } 00212 # endif /* STRUCT_TASK_STRUCT_HAS_CRED */ 00213 #endif /* LINUX_KEYRING_SUPPORT */ 00214 00215 #ifdef STRUCT_TASK_STRUCT_HAS_CRED 00216 static inline int 00217 afs_linux_cred_is_current(afs_ucred_t *cred) 00218 { 00219 return (cred == current_cred()); 00220 } 00221 #else 00222 static inline int 00223 afs_linux_cred_is_current(afs_ucred_t *cred) 00224 { 00225 return 1; 00226 } 00227 #endif 00228 00229 #ifndef HAVE_LINUX_PAGE_OFFSET 00230 static inline loff_t 00231 page_offset(struct page *pp) 00232 { 00233 return (((loff_t) pp->index) << PAGE_CACHE_SHIFT); 00234 } 00235 #endif 00236 00237 #ifndef HAVE_LINUX_ZERO_USER_SEGMENTS 00238 static inline void 00239 zero_user_segments(struct page *pp, unsigned int from1, unsigned int to1, 00240 unsigned int from2, unsigned int to2) 00241 { 00242 void *base = kmap_atomic(pp, KM_USER0); 00243 00244 if (to1 > from1) 00245 memset(base + from1, 0, to1 - from1); 00246 00247 if (to2 > from2) 00248 memset(base + from2, 0, to2 - from2); 00249 00250 flush_dcache_page(pp); 00251 kunmap_atomic(base, KM_USER0); 00252 } 00253 00254 static inline void 00255 zero_user_segment(struct page *pp, unsigned int from1, unsigned int to1) 00256 { 00257 zero_user_segments(pp, from1, to1, 0, 0); 00258 } 00259 #endif 00260 00261 #ifndef HAVE_LINUX_KERNEL_SETSOCKOPT 00262 /* Available from 2.6.19 */ 00263 00264 static inline int 00265 kernel_setsockopt(struct socket *sockp, int level, int name, char *val, 00266 unsigned int len) { 00267 mm_segment_t old_fs = get_fs(); 00268 int ret; 00269 00270 set_fs(get_ds()); 00271 ret = sockp->ops->setsockopt(sockp, level, name, val, len); 00272 set_fs(old_fs); 00273 00274 return ret; 00275 } 00276 00277 static inline int 00278 kernel_getsockopt(struct socket *sockp, int level, int name, char *val, 00279 int *len) { 00280 mm_segment_t old_fs = get_fs(); 00281 int ret; 00282 00283 set_fs(get_ds()); 00284 ret = sockp->ops->getsockopt(sockp, level, name, val, len); 00285 set_fs(old_fs); 00286 00287 return ret; 00288 } 00289 #endif 00290 00291 #ifdef HAVE_TRY_TO_FREEZE 00292 static inline int 00293 afs_try_to_freeze(void) { 00294 # ifdef LINUX_REFRIGERATOR_TAKES_PF_FREEZE 00295 return try_to_freeze(PF_FREEZE); 00296 # else 00297 return try_to_freeze(); 00298 # endif 00299 } 00300 #else 00301 static inline int 00302 afs_try_to_freeze(void) { 00303 # ifdef CONFIG_PM 00304 if (current->flags & PF_FREEZE) { 00305 refrigerator(PF_FREEZE); 00306 return 1; 00307 } 00308 # endif 00309 return 0; 00310 } 00311 #endif 00312 00313 /* The commit which changed refrigerator so that it takes no arguments 00314 * also added freezing(), so if LINUX_REFRIGERATOR_TAKES_PF_FREEZE is 00315 * true, the kernel doesn't have a freezing() function. 00316 */ 00317 #ifdef LINUX_REFRIGERATOR_TAKES_PF_FREEZE 00318 static inline int 00319 freezing(struct task_struct *p) 00320 { 00321 # ifdef CONFIG_PM 00322 return p->flags & PF_FREEZE; 00323 # else 00324 return 0; 00325 # endif 00326 } 00327 #endif 00328 00329 #if !defined(HAVE_LINUX_PAGECHECKED) 00330 # if defined(HAVE_LINUX_PAGEFSMISC) 00331 # include <linux/page-flags.h> 00332 00333 # define PageChecked(p) PageFsMisc((p)) 00334 # define SetPageChecked(p) SetPageFsMisc((p)) 00335 # define ClearPageChecked(p) ClearPageFsMisc((p)) 00336 00337 # endif 00338 #endif 00339 00340 #if !defined(NEW_EXPORT_OPS) 00341 extern struct export_operations export_op_default; 00342 #endif 00343 00344 static inline struct dentry * 00345 afs_get_dentry_from_fh(struct super_block *afs_cacheSBp, afs_dcache_id_t *ainode, 00346 int cache_fh_len, int cache_fh_type, 00347 int (*afs_fh_acceptable)(void *, struct dentry *)) { 00348 #if defined(NEW_EXPORT_OPS) 00349 return afs_cacheSBp->s_export_op->fh_to_dentry(afs_cacheSBp, &ainode->ufs.fh, 00350 cache_fh_len, cache_fh_type); 00351 #else 00352 if (afs_cacheSBp->s_export_op && afs_cacheSBp->s_export_op->decode_fh) 00353 return afs_cacheSBp->s_export_op->decode_fh(afs_cacheSBp, ainode->ufs.raw, 00354 cache_fh_len, cache_fh_type, afs_fh_acceptable, NULL); 00355 else 00356 return export_op_default.decode_fh(afs_cacheSBp, ainode->ufs.raw, 00357 cache_fh_len, cache_fh_type, afs_fh_acceptable, NULL); 00358 #endif 00359 } 00360 00361 static inline int 00362 afs_get_fh_from_dentry(struct dentry *dp, afs_ufs_dcache_id_t *ainode, int *max_lenp) { 00363 if (dp->d_sb->s_export_op->encode_fh) 00364 #if defined(EXPORT_OP_ENCODE_FH_TAKES_INODES) 00365 return dp->d_sb->s_export_op->encode_fh(dp->d_inode, &ainode->raw[0], max_lenp, NULL); 00366 #else 00367 return dp->d_sb->s_export_op->encode_fh(dp, &ainode->raw[0], max_lenp, 0); 00368 #endif 00369 #if defined(NEW_EXPORT_OPS) 00370 /* If fs doesn't provide an encode_fh method, assume the default INO32 type */ 00371 *max_lenp = sizeof(struct fid)/4; 00372 ainode->fh.i32.ino = dp->d_inode->i_ino; 00373 ainode->fh.i32.gen = dp->d_inode->i_generation; 00374 return FILEID_INO32_GEN; 00375 #else 00376 /* or call the default encoding function for the old API */ 00377 return export_op_default.encode_fh(dp, &ainode->raw[0], max_lenp, 0); 00378 #endif 00379 } 00380 00381 static inline void 00382 afs_init_sb_export_ops(struct super_block *sb) { 00383 #if !defined(NEW_EXPORT_OPS) 00384 /* 00385 * decode_fh will call this function. If not defined for this FS, make 00386 * sure it points to the default 00387 */ 00388 if (!sb->s_export_op->find_exported_dentry) { 00389 /* Some kernels (at least 2.6.9) do not prototype find_exported_dentry, 00390 * even though it is exported, so prototype it ourselves. Newer 00391 * kernels do prototype it, but as long as our protoype matches the 00392 * real one (the signature never changed before NEW_EXPORT_OPS came 00393 * into play), there should be no problems. */ 00394 extern struct dentry * find_exported_dentry(struct super_block *sb, void *obj, void *parent, 00395 int (*acceptable)(void *context, struct dentry *de), 00396 void *context); 00397 sb->s_export_op->find_exported_dentry = find_exported_dentry; 00398 } 00399 #endif 00400 } 00401 00402 static inline void 00403 afs_linux_lock_inode(struct inode *ip) { 00404 #ifdef STRUCT_INODE_HAS_I_MUTEX 00405 mutex_lock(&ip->i_mutex); 00406 #else 00407 down(&ip->i_sem); 00408 #endif 00409 } 00410 00411 static inline void 00412 afs_linux_unlock_inode(struct inode *ip) { 00413 #ifdef STRUCT_INODE_HAS_I_MUTEX 00414 mutex_unlock(&ip->i_mutex); 00415 #else 00416 up(&ip->i_sem); 00417 #endif 00418 } 00419 00420 static inline int 00421 afs_inode_setattr(struct osi_file *afile, struct iattr *newattrs) { 00422 00423 int code = 0; 00424 struct inode *inode = OSIFILE_INODE(afile); 00425 #if !defined(HAVE_LINUX_INODE_SETATTR) 00426 code = inode->i_op->setattr(afile->filp->f_dentry, newattrs); 00427 #elif defined(INODE_SETATTR_NOT_VOID) 00428 if (inode->i_op && inode->i_op->setattr) 00429 code = inode->i_op->setattr(afile->filp->f_dentry, newattrs); 00430 else 00431 code = inode_setattr(inode, newattrs); 00432 #else 00433 inode_setattr(inode, newattrs); 00434 #endif 00435 return code; 00436 } 00437 00438 #if defined(HAVE_LINUX_PATH_LOOKUP) 00439 static inline int 00440 afs_kern_path(char *aname, int flags, struct nameidata *nd) { 00441 return path_lookup(aname, flags, nd); 00442 } 00443 #else 00444 static inline int 00445 afs_kern_path(char *aname, int flags, afs_linux_path_t *path) { 00446 return kern_path(aname, flags, path); 00447 } 00448 #endif 00449 00450 static inline void 00451 #if defined(HAVE_LINUX_PATH_LOOKUP) 00452 afs_get_dentry_ref(struct nameidata *nd, struct vfsmount **mnt, struct dentry **dpp) { 00453 #else 00454 afs_get_dentry_ref(afs_linux_path_t *path, struct vfsmount **mnt, struct dentry **dpp) { 00455 #endif 00456 #if defined(STRUCT_NAMEIDATA_HAS_PATH) 00457 # if defined(HAVE_LINUX_PATH_LOOKUP) 00458 *dpp = dget(nd->path.dentry); 00459 if (mnt) 00460 *mnt = mntget(nd->path.mnt); 00461 path_put(&nd->path); 00462 # else 00463 *dpp = dget(path->dentry); 00464 if (mnt) 00465 *mnt = mntget(path->mnt); 00466 path_put(path); 00467 # endif 00468 #else 00469 *dpp = dget(nd->dentry); 00470 if (mnt) 00471 *mnt = mntget(nd->mnt); 00472 path_release(nd); 00473 #endif 00474 } 00475 00476 /* wait_event_freezable appeared with 2.6.24 */ 00477 00478 /* These implement the original AFS wait behaviour, with respect to the 00479 * refrigerator, rather than the behaviour of the current wait_event_freezable 00480 * implementation. 00481 */ 00482 00483 #ifndef wait_event_freezable 00484 # define wait_event_freezable(waitqueue, condition) \ 00485 ({ \ 00486 int _ret; \ 00487 do { \ 00488 _ret = wait_event_interruptible(waitqueue, \ 00489 (condition) || freezing(current)); \ 00490 if (_ret && !freezing(current)) \ 00491 break; \ 00492 else if (!(condition)) \ 00493 _ret = -EINTR; \ 00494 } while (afs_try_to_freeze()); \ 00495 _ret; \ 00496 }) 00497 00498 # define wait_event_freezable_timeout(waitqueue, condition, timeout) \ 00499 ({ \ 00500 int _ret; \ 00501 do { \ 00502 _ret = wait_event_interruptible_timeout(waitqueue, \ 00503 (condition || \ 00504 freezing(current)), \ 00505 timeout); \ 00506 } while (afs_try_to_freeze()); \ 00507 _ret; \ 00508 }) 00509 #endif 00510 00511 #if defined(STRUCT_TASK_STRUCT_HAS_CRED) 00512 static inline struct file * 00513 afs_dentry_open(struct dentry *dp, struct vfsmount *mnt, int flags, const struct cred *creds) { 00514 #if defined(DENTRY_OPEN_TAKES_PATH) 00515 afs_linux_path_t path; 00516 struct file *filp; 00517 path.mnt = mnt; 00518 path.dentry = dp; 00519 filp = dentry_open(&path, flags, creds); 00520 return filp; 00521 #else 00522 return dentry_open(dp, mntget(mnt), flags, creds); 00523 #endif 00524 } 00525 #endif 00526 00527 #endif /* AFS_LINUX_OSI_COMPAT_H */