From 926d692d223b876ba7cc78e0be093eb80369dd79 Mon Sep 17 00:00:00 2001 From: green Date: Wed, 14 Jun 2006 20:26:10 +0000 Subject: [PATCH] patchless support. --- lustre/autoconf/lustre-core.m4 | 60 +++++++++ lustre/include/linux/Makefile.am | 2 +- lustre/include/linux/lustre_compat25.h | 25 ++++ lustre/include/linux/lustre_intent.h | 35 +++++ lustre/include/linux/lustre_mds.h | 17 ++- lustre/include/linux/lustre_patchless_compat.h | 78 +++++++++++ lustre/include/linux/lvfs_linux.h | 1 + lustre/ldlm/ldlm_lock.c | 1 + lustre/llite/dcache.c | 158 ++++++++++++++++++++++- lustre/llite/file.c | 18 ++- lustre/llite/llite_internal.h | 25 +++- lustre/llite/llite_lib.c | 41 ++++-- lustre/llite/namei.c | 171 ++++++++++++++++++++++++- lustre/llite/symlink.c | 16 ++- lustre/llite/xattr.c | 23 ++-- lustre/lvfs/lvfs_linux.c | 6 +- lustre/mdc/mdc_lib.c | 1 - lustre/ptlrpc/service.c | 2 +- 18 files changed, 635 insertions(+), 45 deletions(-) create mode 100644 lustre/include/linux/lustre_intent.h create mode 100644 lustre/include/linux/lustre_patchless_compat.h diff --git a/lustre/autoconf/lustre-core.m4 b/lustre/autoconf/lustre-core.m4 index f1d257b..a488504 100644 --- a/lustre/autoconf/lustre-core.m4 +++ b/lustre/autoconf/lustre-core.m4 @@ -506,6 +506,62 @@ AC_DEFUN([LC_XATTR_ACL], []) ]) +AC_DEFUN([LC_STRUCT_INTENT_FILE], +[AC_MSG_CHECKING([if struct open_intent has a file field]) +LB_LINUX_TRY_COMPILE([ + #include + #include +],[ + struct open_intent intent; + &intent.file; +],[ + AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_FILE_IN_STRUCT_INTENT, 1, [struct open_intent has a file field]) +],[ + AC_MSG_RESULT([no]) +]) +]) + + +AC_DEFUN([LC_POSIX_ACL_XATTR_H], +[LB_CHECK_FILE([$LINUX/include/linux/posix_acl_xattr.h],[ + AC_MSG_CHECKING([if linux/posix_acl_xattr.h can be compiled]) + LB_LINUX_TRY_COMPILE([ + #include + ],[],[ + AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_LINUX_POSIX_ACL_XATTR_H, 1, [linux/posix_acl_xattr.h found]) + + ],[ + AC_MSG_RESULT([no]) + ]) +$1 +],[ +AC_MSG_RESULT([no]) +]) +]) + +AC_DEFUN([LC_LUSTRE_VERSION_H], +[LB_CHECK_FILE([$LINUX/include/linux/lustre_version.h],[ + rm -f "$LUSTRE/include/linux/lustre_version.h" +],[ + touch "$LUSTRE/include/linux/lustre_version.h" +]) +]) + +AC_DEFUN([LC_FUNC_SET_FS_PWD], +[AC_MSG_CHECKING([if kernel exports show_task]) +have_show_task=0 + if grep -q "EXPORT_SYMBOL(show_task)" \ + "$LINUX/fs/namespace.c" 2>/dev/null ; then + AC_DEFINE(HAVE_SET_FS_PWD, 1, [set_fs_pwd is exported]) + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi +]) + + # # LC_PROG_LINUX # @@ -535,6 +591,10 @@ LC_STRUCT_FILE_OPS_UNLOCKED_IOCTL LC_FILEMAP_POPULATE LC_D_ADD_UNIQUE LC_XATTR_ACL +LC_STRUCT_INTENT_FILE +LC_POSIX_ACL_XATTR_H +LC_LUSTRE_VERSION_H +LC_FUNC_SET_FS_PWD ]) # diff --git a/lustre/include/linux/Makefile.am b/lustre/include/linux/Makefile.am index 72fdd51..9604a6a 100644 --- a/lustre/include/linux/Makefile.am +++ b/lustre/include/linux/Makefile.am @@ -13,5 +13,5 @@ EXTRA_DIST = lprocfs_status.h lustre_debug.h lustre_lib.h \ lustre_dlm.h lustre_handles.h lustre_net.h obd_class.h obd_support.h \ lustre_log.h lustre_compat25.h lustre_fsfilt.h lustre_mds.h obd.h \ lvfs.h lvfs_linux.h lustre_lite.h lustre_quota.h \ - lustre_user.h lustre_types.h + lustre_user.h lustre_types.h lustre_patchless_compat.h lustre_intent.h diff --git a/lustre/include/linux/lustre_compat25.h b/lustre/include/linux/lustre_compat25.h index ffeffaf..d3f55f3 100644 --- a/lustre/include/linux/lustre_compat25.h +++ b/lustre/include/linux/lustre_compat25.h @@ -31,6 +31,8 @@ #include +#include + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) struct ll_iattr_struct { struct iattr iattr; @@ -40,6 +42,29 @@ struct ll_iattr_struct { #define ll_iattr_struct iattr #endif +#ifndef HAVE_SET_FS_PWD +static inline void ll_set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt, + struct dentry *dentry) +{ + struct dentry *old_pwd; + struct vfsmount *old_pwdmnt; + + write_lock(&fs->lock); + old_pwd = fs->pwd; + old_pwdmnt = fs->pwdmnt; + fs->pwdmnt = mntget(mnt); + fs->pwd = dget(dentry); + write_unlock(&fs->lock); + + if (old_pwd) { + dput(old_pwd); + mntput(old_pwdmnt); + } +} +#else +#define ll_set_fs_pwd set_fs_pwd +#endif + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) #define UNLOCK_INODE_MUTEX(inode) do {mutex_unlock(&(inode)->i_mutex); } while(0) #define LOCK_INODE_MUTEX(inode) do {mutex_lock(&(inode)->i_mutex); } while(0) diff --git a/lustre/include/linux/lustre_intent.h b/lustre/include/linux/lustre_intent.h new file mode 100644 index 0000000..3d8cb2c --- /dev/null +++ b/lustre/include/linux/lustre_intent.h @@ -0,0 +1,35 @@ +#ifndef LUSTRE_INTENT_H +#define LUSTRE_INTENT_H + +#include + +#ifndef LUSTRE_KERNEL_VERSION +#define IT_OPEN (1) +#define IT_CREAT (1<<1) +#define IT_READDIR (1<<2) +#define IT_GETATTR (1<<3) +#define IT_LOOKUP (1<<4) +#define IT_UNLINK (1<<5) +#define IT_TRUNC (1<<6) +#define IT_GETXATTR (1<<7) + +struct lustre_intent_data { + int it_disposition; + int it_status; + __u64 it_lock_handle; + void *it_data; + int it_lock_mode; +}; + +struct lookup_intent { + int it_op; + int it_flags; + int it_create_mode; + union { + struct lustre_intent_data lustre; + } d; +}; + + +#endif +#endif diff --git a/lustre/include/linux/lustre_mds.h b/lustre/include/linux/lustre_mds.h index 6c58556..8e4c08e 100644 --- a/lustre/include/linux/lustre_mds.h +++ b/lustre/include/linux/lustre_mds.h @@ -17,12 +17,17 @@ #ifdef __KERNEL__ # include # include - -#ifdef HAVE_XATTR_ACL -#include -#else -#include -#endif +# ifdef CONFIG_FS_POSIX_ACL +# ifdef HAVE_XATTR_ACL +# include +# endif +# ifdef HAVE_LINUX_POSIX_ACL_XATTR_H +# include +# endif +# endif +# ifndef LUSTRE_KERNEL_VERSION +# include +# endif #endif struct ldlm_lock_desc; diff --git a/lustre/include/linux/lustre_patchless_compat.h b/lustre/include/linux/lustre_patchless_compat.h new file mode 100644 index 0000000..63cad57 --- /dev/null +++ b/lustre/include/linux/lustre_patchless_compat.h @@ -0,0 +1,78 @@ +#ifndef LUSTRE_PATCHLESS_COMPAT_H +#define LUSTRE_PATCHLESS_COMPAT_H + +#include +#ifndef LUSTRE_KERNEL_VERSION +#include + +#ifndef HAVE_TRUNCATE_COMPLETE_PAGE +#include +#include +#include + +/* XXX copy & paste from 2.6.15 kernel */ +static inline void ll_remove_from_page_cache(struct page *page) +{ + struct address_space *mapping = page->mapping; + + BUG_ON(!PageLocked(page)); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) + write_lock_irq(&mapping->tree_lock); +#else + spin_lock_irq(&mapping->tree_lock); +#endif + radix_tree_delete(&mapping->page_tree, page->index); + page->mapping = NULL; + mapping->nrpages--; + atomic_add(-1, &nr_pagecache); // XXX pagecache_acct(-1); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) + write_unlock_irq(&mapping->tree_lock); +#else + spin_unlock_irq(&mapping->tree_lock); +#endif +} + +static inline void +truncate_complete_page(struct address_space *mapping, struct page *page) +{ + if (page->mapping != mapping) + return; + + if (PagePrivate(page)) + page->mapping->a_ops->invalidatepage(page, 0); + + clear_page_dirty(page); + ClearPageUptodate(page); + ClearPageMappedToDisk(page); + ll_remove_from_page_cache(page); + page_cache_release(page); /* pagecache ref */ +} +#endif + +/* megahack */ +static inline void d_rehash_cond(struct dentry * entry, int lock) +{ + if (!lock) + spin_unlock(&dcache_lock); + + d_rehash(entry); + + if (!lock) + spin_lock(&dcache_lock); +} + +#define __d_rehash(dentry, lock) d_rehash_cond(dentry, lock) + +#define LUSTRE_PATCHLESS + +#ifndef ATTR_FROM_OPEN +#define ATTR_FROM_OPEN 0 +#endif +#ifndef ATTR_RAW +#define ATTR_RAW 0 +#endif + +#endif /* LUSTRE_KERNEL_VERSION */ + +#endif diff --git a/lustre/include/linux/lvfs_linux.h b/lustre/include/linux/lvfs_linux.h index 0ea6104..5c466ce 100644 --- a/lustre/include/linux/lvfs_linux.h +++ b/lustre/include/linux/lvfs_linux.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include diff --git a/lustre/ldlm/ldlm_lock.c b/lustre/ldlm/ldlm_lock.c index ba6f7b4..4d813d6 100644 --- a/lustre/ldlm/ldlm_lock.c +++ b/lustre/ldlm/ldlm_lock.c @@ -28,6 +28,7 @@ #ifdef __KERNEL__ # include +# include #else # include # include diff --git a/lustre/llite/dcache.c b/lustre/llite/dcache.c index ebdf8e8..0c681ea 100644 --- a/lustre/llite/dcache.c +++ b/lustre/llite/dcache.c @@ -45,6 +45,12 @@ static void ll_release(struct dentry *de) EXIT; return; } +#ifndef LUSTRE_KERNEL_VERSION + if (lld->lld_it) { + ll_intent_release(lld->lld_it); + OBD_FREE(lld->lld_it, sizeof(*lld->lld_it)); + } +#endif LASSERT(lld->lld_cwd_count == 0); LASSERT(lld->lld_mnt_count == 0); OBD_FREE(de->d_fsdata, sizeof(*lld)); @@ -52,6 +58,7 @@ static void ll_release(struct dentry *de) EXIT; } +#ifdef LUSTRE_KERNEL_VERSION /* Compare if two dentries are the same. Don't match if the existing dentry * is marked DCACHE_LUSTRE_INVALID. Returns 1 if different, 0 if the same. * @@ -80,17 +87,26 @@ int ll_dcompare(struct dentry *parent, struct qstr *d_name, struct qstr *name) RETURN(0); } +#endif /* should NOT be called with the dcache lock, see fs/dcache.c */ static int ll_ddelete(struct dentry *de) { ENTRY; LASSERT(de); +#ifndef DCACHE_LUSTRE_INVALID +#define DCACHE_LUSTRE_INVALID 0 +#endif + CDEBUG(D_DENTRY, "%s dentry %.*s (%p, parent %p, inode %p) %s%s\n", (de->d_flags & DCACHE_LUSTRE_INVALID ? "deleting" : "keeping"), de->d_name.len, de->d_name.name, de, de->d_parent, de->d_inode, d_unhashed(de) ? "" : "hashed,", list_empty(&de->d_subdirs) ? "" : "subdirs"); +#if DCACHE_LUSTRE_INVALID == 0 +#undef DCACHE_LUSTRE_INVALID +#endif + RETURN(0); } @@ -132,8 +148,10 @@ void ll_intent_release(struct lookup_intent *it) ENTRY; ll_intent_drop_lock(it); +#ifdef LUSTRE_KERNEL_VERSION it->it_magic = 0; it->it_op_release = 0; +#endif /* We are still holding extra reference on a request, need to free it */ if (it_disposition(it, DISP_ENQ_OPEN_REF)) /* open req for llfile_open*/ ptlrpc_req_finished(it->d.lustre.it_data); @@ -168,8 +186,10 @@ int ll_drop_dentry(struct dentry *dentry) return 1; } +#ifdef LUSTRE_KERNEL_VERSION if (!(dentry->d_flags & DCACHE_LUSTRE_INVALID)) { -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +#else + if (!d_unhashed(dentry)) { struct inode *inode = dentry->d_inode; #endif CDEBUG(D_DENTRY, "unhashing dentry %.*s (%p) parent %p " @@ -179,7 +199,13 @@ int ll_drop_dentry(struct dentry *dentry) /* actually we don't unhash the dentry, rather just * mark it inaccessible for to __d_lookup(). otherwise * sys_getcwd() could return -ENOENT -bzzz */ +#ifdef LUSTRE_KERNEL_VERSION dentry->d_flags |= DCACHE_LUSTRE_INVALID; +#else + if (!inode || !S_ISDIR(inode->i_mode)) + __d_drop(dentry); +#endif + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) __d_drop(dentry); if (inode) { @@ -284,7 +310,7 @@ void ll_lookup_finish_locks(struct lookup_intent *it, struct dentry *dentry) void ll_frob_intent(struct lookup_intent **itp, struct lookup_intent *deft) { struct lookup_intent *it = *itp; -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#if defined(LUSTRE_KERNEL_VERSION)&&(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) if (it) { LASSERTF(it->it_magic == INTENT_MAGIC, "bad intent magic: %x\n", it->it_magic); @@ -294,7 +320,9 @@ void ll_frob_intent(struct lookup_intent **itp, struct lookup_intent *deft) if (!it || it->it_op == IT_GETXATTR) it = *itp = deft; +#ifdef LUSTRE_KERNEL_VERSION it->it_op_release = ll_intent_release; +#endif } int ll_revalidate_it(struct dentry *de, int lookup_flags, @@ -319,8 +347,10 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags, if (it && (it->it_op & IT_CREAT)) RETURN(0); +#ifdef LUSTRE_KERNEL_VERSION if (de->d_flags & DCACHE_LUSTRE_INVALID) RETURN(0); +#endif rc = ll_have_md_lock(de->d_parent->d_inode, MDS_INODELOCK_UPDATE); @@ -335,6 +365,11 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags, if (d_mountpoint(de)) RETURN(1); + /* Root of the lustre tree. Always valid. + * Attributes will be fixed up in ll_inode_revalidate_it */ + if (de->d_name.name[0] == '/' && de->d_name.len == 1) + RETURN(1); + OBD_FAIL_TIMEOUT(OBD_FAIL_MDC_REVALIDATE_PAUSE, 5); ll_frob_intent(&it, &lookup_it); LASSERT(it); @@ -393,8 +428,11 @@ do_lock: &req, ll_mdc_blocking_ast, 0); /* If req is NULL, then mdc_intent_lock only tried to do a lock match; * if all was well, it will return 1 if it found locks, 0 otherwise. */ - if (req == NULL && rc >= 0) + if (req == NULL && rc >= 0) { + if (!rc) + goto do_lookup; GOTO(out, rc); + } if (rc < 0) { if (rc != -ESTALE) { @@ -404,6 +442,7 @@ do_lock: GOTO(out, rc = 0); } +revalidate_finish: rc = revalidate_it_finish(req, DLM_REPLY_REC_OFF, it, de); if (rc != 0) { ll_intent_release(it); @@ -433,20 +472,60 @@ do_lock: if (req != NULL && !it_disposition(it, DISP_ENQ_COMPLETE)) ptlrpc_req_finished(req); if (rc == 0) { +#ifdef LUSTRE_KERNEL_VERSION ll_unhash_aliases(de->d_inode); /* done in ll_unhash_aliases() dentry->d_flags |= DCACHE_LUSTRE_INVALID; */ +#else + /* We do not want d_invalidate to kill all child dentries too */ + d_drop(de); +#endif } else { CDEBUG(D_DENTRY, "revalidated dentry %.*s (%p) parent %p " "inode %p refc %d\n", de->d_name.len, de->d_name.name, de, de->d_parent, de->d_inode, atomic_read(&de->d_count)); ll_lookup_finish_locks(it, de); +#ifdef LUSTRE_KERNEL_VERSION lock_dentry(de); de->d_flags &= ~DCACHE_LUSTRE_INVALID; unlock_dentry(de); +#endif } RETURN(rc); +/* This part is here to combat evil-evil race in real_lookup on 2.6 kernels. + * The race details are: We enter do_lookup() looking for some name, + * there is nothing in dcache for this name yet and d_lookup() returns NULL. + * We proceed to real_lookup(), and while we do this, another process does + * open on the same file we looking up (most simple reproducer), open succeeds + * and the dentry is added. Now back to us. In real_lookup() we do d_lookup() + * again and suddenly find the dentry, so we call d_revalidate on it, but there + * is no lock, so without this code we would return 0, but unpatched + * real_lookup just returns -ENOENT in such a case instead of retrying the + * lookup. Once this is dealt with in real_lookup(), all of this ugly mess + * can go and we can just check locks in ->d_revalidate without doing any + * RPCs ever. */ +do_lookup: + if (it != &lookup_it) { + ll_lookup_finish_locks(it, de); + it = &lookup_it; + } + /*do real lookup here */ + ll_prepare_mdc_op_data(&op_data, de->d_parent->d_inode, NULL, + de->d_name.name, de->d_name.len, 0); + rc = mdc_intent_lock(exp, &op_data, NULL, 0, it, 0, &req, + ll_mdc_blocking_ast, 0); + if (rc >= 0) { + struct mds_body *mds_body = lustre_msg_buf(req->rq_repmsg, + DLM_REPLY_REC_OFF, + sizeof(*mds_body)); + /* see if we got same inode, if not - return error */ + if(!memcmp(&op_data.fid2, &mds_body->fid1, + sizeof(op_data.fid2))) + goto revalidate_finish; + ll_intent_release(it); + } + GOTO(out, rc = 0); } /*static*/ void ll_pin(struct dentry *de, struct vfsmount *mnt, int flag) @@ -534,6 +613,7 @@ do_lock: } #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#ifdef LUSTRE_KERNEL_VERSION static int ll_revalidate_nd(struct dentry *dentry, struct nameidata *nd) { int rc; @@ -546,6 +626,76 @@ static int ll_revalidate_nd(struct dentry *dentry, struct nameidata *nd) RETURN(rc); } +#else +int ll_revalidate_nd(struct dentry *dentry, struct nameidata *nd) +{ + int rc; + ENTRY; + + if (nd && !(nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT))) { + struct lookup_intent *it; + it = ll_convert_intent(&nd->intent.open, nd->flags); + if (IS_ERR(it)) + RETURN(0); + if (it->it_op == (IT_OPEN|IT_CREAT)) + if (nd->intent.open.flags & O_EXCL) { + CDEBUG(D_VFSTRACE, "create O_EXCL, returning 0\n"); + rc = 0; + goto out_it; + } + + rc = ll_revalidate_it(dentry, nd->flags, it); + + if (rc && (nd->flags & LOOKUP_OPEN) && + it_disposition(it, DISP_OPEN_OPEN)) {/*Open*/ +#ifdef HAVE_FILE_IN_STRUCT_INTENT +// XXX Code duplication with ll_lookup_nd + if (S_ISFIFO(dentry->d_inode->i_mode)) { + // We cannot call open here as it would + // deadlock. + ptlrpc_req_finished( + (struct ptlrpc_request *) + it->d.lustre.it_data); + } else { + struct file *filp; + + nd->intent.open.file->private_data = it; + filp = lookup_instantiate_filp(nd, dentry,NULL); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)) +/* 2.6.1[456] have a bug in open_namei() that forgets to check + * nd->intent.open.file for error, so we need to return it as lookup's result + * instead */ + if (IS_ERR(filp)) + rc = 0; +#endif + } +#else + ll_release_openhandle(dentry, it); +#endif /* HAVE_FILE_IN_STRUCT_INTENT */ + } + if (!rc && (nd->flags & LOOKUP_CREATE) && + it_disposition(it, DISP_OPEN_CREATE)) { + /* We created something but we may only return + * negative dentry here, so save request in dentry, + * if lookup will be called later on, it will + * pick the request, otherwise it would be freed + * with dentry */ + ll_d2d(dentry)->lld_it = it; + it = NULL; /* avoid freeing */ + } + +out_it: + if (it) { + ll_intent_release(it); + OBD_FREE(it, sizeof(*it)); + } + } else { + rc = ll_revalidate_it(dentry, 0, NULL); + } + + RETURN(rc); +} +#endif #endif struct dentry_operations ll_d_ops = { @@ -556,7 +706,9 @@ struct dentry_operations ll_d_ops = { #endif .d_release = ll_release, .d_delete = ll_ddelete, +#ifdef LUSTRE_KERNEL_VERSION .d_compare = ll_dcompare, +#endif #if 0 .d_pin = ll_pin, .d_unpin = ll_unpin, diff --git a/lustre/llite/file.c b/lustre/llite/file.c index f5f3f89..0bcdc7c 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -371,7 +371,12 @@ int ll_file_open(struct inode *inode, struct file *file) if (inode->i_sb->s_root == file->f_dentry) RETURN(0); +#ifdef LUSTRE_KERNEL_VERSION it = file->f_it; +#else + it = file->private_data; /* XXX: compat macro */ + file->private_data = NULL; /* prevent ll_local_open assertion */ +#endif fd = ll_file_data_get(); if (fd == NULL) @@ -389,6 +394,15 @@ int ll_file_open(struct inode *inode, struct file *file) if (oit.it_flags & O_CREAT) oit.it_flags |= MDS_OPEN_OWNEROVERRIDE; + /* NFS hack - some strange NFS clients create files with zero + * permission bits, and then expect to be able to open such + * files. We are relying on real VFS client to do ll_permission + * first before coming here, so if we got here, we either came + * from NFS or all access checks ar eok, so it is safe to set + * this flag in any case (XXX - race with chmod?) + */ + oit.it_flags |= MDS_OPEN_OWNEROVERRIDE; + /* We do not want O_EXCL here, presumably we opened the file * already? XXX - NFS implications? */ oit.it_flags &= ~O_EXCL; @@ -2326,11 +2340,13 @@ struct file_operations ll_file_operations_flock = { struct inode_operations ll_file_inode_operations = { +#ifdef LUSTRE_KERNEL_VERSION .setattr_raw = ll_setattr_raw, +#endif .setattr = ll_setattr, .truncate = ll_truncate, #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) - .getattr_it = ll_getattr_it, + .getattr = ll_getattr, #else .revalidate_it = ll_inode_revalidate_it, #endif diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index 67f1024..f9846e9 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -7,10 +7,11 @@ #ifdef CONFIG_FS_POSIX_ACL # include -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) -#include -#else -#include +#ifdef HAVE_XATTR_ACL +# include +#endif +#ifdef HAVE_LINUX_POSIX_ACL_XATTR_H +# include #endif #endif @@ -27,8 +28,13 @@ struct lustre_intent_data { __u32 it_lock_mode; }; */ +/* If there is no FMODE_EXEC defined, make it to match nothing */ +#ifndef FMODE_EXEC +#define FMODE_EXEC 0 +#endif + #define LL_IT2STR(it) ((it) ? ldlm_it2str((it)->it_op) : "0") -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) +#if !defined(LUSTRE_KERNEL_VERSION) || (LUSTRE_KERNEL_VERSION < 46) #define LUSTRE_FPRIVATE(file) ((file)->private_data) #else #if (LUSTRE_KERNEL_VERSION < 46) @@ -38,6 +44,7 @@ struct lustre_intent_data { #endif #endif +#ifdef LUSTRE_KERNEL_VERSION static inline struct lookup_intent *ll_nd2it(struct nameidata *nd) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) @@ -46,12 +53,16 @@ static inline struct lookup_intent *ll_nd2it(struct nameidata *nd) return nd->intent; #endif } +#endif struct ll_dentry_data { int lld_cwd_count; int lld_mnt_count; struct obd_client_handle lld_cwd_och; struct obd_client_handle lld_mnt_och; +#ifndef LUSTRE_KERNEL_VERSION + struct lookup_intent *lld_it; +#endif }; #define ll_d2d(de) ((struct ll_dentry_data*) de->d_fsdata) @@ -378,6 +389,10 @@ int ll_mdc_blocking_ast(struct ldlm_lock *, struct ldlm_lock_desc *, void ll_prepare_mdc_op_data(struct mdc_op_data *, struct inode *i1, struct inode *i2, const char *name, int namelen, int mode); +#ifndef LUSTRE_KERNEL_VERSION +struct lookup_intent *ll_convert_intent(struct open_intent *oit, + int lookup_flags); +#endif /* llite/rw.c */ int ll_prepare_write(struct file *, struct page *, unsigned from, unsigned to); diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index b233bd1..b1e41ee 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -103,7 +103,9 @@ void ll_free_sbi(struct super_block *sb) } static struct dentry_operations ll_d_root_ops = { +#ifdef LUSTRE_KERNEL_VERSION .d_compare = ll_dcompare, +#endif }; int client_common_fill_super(struct super_block *sb, char *mdc, char *osc) @@ -1064,8 +1066,12 @@ void ll_clear_inode(struct inode *inode) if (lli->lli_mds_write_och) ll_mdc_real_close(inode, FMODE_WRITE); - if (lli->lli_mds_exec_och) + if (lli->lli_mds_exec_och) { + if (!FMODE_EXEC) + CERROR("No FMODE exec, bug exec och is present for " + "inode %ld\n", inode->i_ino); ll_mdc_real_close(inode, FMODE_EXEC); + } if (lli->lli_mds_read_och) ll_mdc_real_close(inode, FMODE_READ); @@ -1290,32 +1296,41 @@ int ll_setattr_raw(struct inode *inode, struct iattr *attr) } else if (ia_valid & (ATTR_MTIME | ATTR_MTIME_SET)) { obd_flag flags; struct obd_info oinfo = { { { 0 } } }; - struct obdo oa; + struct obdo *oa = obdo_alloc(); CDEBUG(D_INODE, "set mtime on OST inode %lu to %lu\n", inode->i_ino, LTIME_S(attr->ia_mtime)); - oa.o_id = lsm->lsm_object_id; - oa.o_valid = OBD_MD_FLID; + if (oa) { + oa->o_id = lsm->lsm_object_id; + oa->o_valid = OBD_MD_FLID; - flags = OBD_MD_FLTYPE | OBD_MD_FLATIME | - OBD_MD_FLMTIME | OBD_MD_FLCTIME | - OBD_MD_FLFID | OBD_MD_FLGENER; + flags = OBD_MD_FLTYPE | OBD_MD_FLATIME | + OBD_MD_FLMTIME | OBD_MD_FLCTIME | + OBD_MD_FLFID | OBD_MD_FLGENER; - obdo_from_inode(&oa, inode, flags); + obdo_from_inode(oa, inode, flags); - oinfo.oi_oa = &oa; - oinfo.oi_md = lsm; + oinfo.oi_oa = oa; + oinfo.oi_md = lsm; - rc = obd_setattr_rqset(sbi->ll_osc_exp, &oinfo, NULL); - if (rc) - CERROR("obd_setattr_async fails: rc=%d\n", rc); + rc = obd_setattr_rqset(sbi->ll_osc_exp, &oinfo, NULL); + if (rc) + CERROR("obd_setattr_async fails: rc=%d\n", rc); + obdo_free(oa); + } else { + rc = -ENOMEM; + } } RETURN(rc); } int ll_setattr(struct dentry *de, struct iattr *attr) { + if ((attr->ia_valid & (ATTR_CTIME|ATTR_SIZE|ATTR_MODE)) == + (ATTR_CTIME|ATTR_SIZE|ATTR_MODE)) + attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE; + return ll_setattr_raw(de->d_inode, attr); } diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index 33cfa18..26a71df 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -188,6 +188,8 @@ int ll_mdc_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, break; case LCK_PR: flags = FMODE_EXEC; + if (!FMODE_EXEC) + CERROR("open PR lock without FMODE_EXEC\n"); break; case LCK_CR: flags = FMODE_READ; @@ -223,7 +225,11 @@ int ll_mdc_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, racer?) */ while ((list = list->next) != &inode->i_dentry) { dir = list_entry(list, struct dentry, d_alias); +#ifdef LUSTRE_KERNEL_VERSION if (!(dir->d_flags & DCACHE_LUSTRE_INVALID)) +#else + if (!d_unhashed(dir)) +#endif break; dir = NULL; @@ -393,7 +399,9 @@ struct dentry *ll_find_alias(struct inode *inode, struct dentry *de) dget_locked(dentry); lock_dentry(dentry); __d_drop(dentry); +#ifdef LUSTRE_KERNEL_VERSION dentry->d_flags &= ~DCACHE_LUSTRE_INVALID; +#endif unlock_dentry(dentry); __d_rehash(dentry, 0); /* avoid taking dcache_lock inside */ spin_unlock(&dcache_lock); @@ -416,11 +424,13 @@ struct dentry *ll_find_alias(struct inode *inode, struct dentry *de) struct dentry *dentry; dentry = d_add_unique(de, inode); +#ifdef LUSTRE_KERNEL_VERSION if (dentry) { lock_dentry(dentry); dentry->d_flags &= ~DCACHE_LUSTRE_INVALID; unlock_dentry(dentry); } +#endif return dentry?dentry:de; } @@ -541,6 +551,7 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, } #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#ifdef LUSTRE_KERNEL_VERSION static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry, struct nameidata *nd) { @@ -554,6 +565,120 @@ static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry, RETURN(de); } +#else +struct lookup_intent *ll_convert_intent(struct open_intent *oit, + int lookup_flags) +{ + struct lookup_intent *it; + + OBD_ALLOC(it, sizeof(*it)); + if (!it) + return ERR_PTR(-ENOMEM); + + if (lookup_flags & LOOKUP_OPEN) { + it->it_op = IT_OPEN; + if (lookup_flags & LOOKUP_CREATE) + it->it_op |= IT_CREAT; + it->it_create_mode = oit->create_mode; + it->it_flags = oit->flags; + } else { + it->it_op = IT_GETATTR; + } + +#ifndef HAVE_FILE_IN_STRUCT_INTENT + /* Since there is no way to pass our intent to ll_file_open, + * just check the file is there. Actual open will be done + * in ll_file_open */ + if (it->it_op & IT_OPEN) + it->it_op = IT_LOOKUP; +#endif + + return it; +} + +static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry, + struct nameidata *nd) +{ + struct dentry *de; + ENTRY; + + if (nd && !(nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT))) { + struct lookup_intent *it; + +#if defined(HAVE_FILE_IN_STRUCT_INTENT) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)) + /* Did we came here from failed revalidate just to propagate + * its error? */ + if (nd->flags & LOOKUP_OPEN) + if (IS_ERR(nd->intent.open.file)) + RETURN((struct dentry *)nd->intent.open.file); +#endif + + if (ll_d2d(dentry) && ll_d2d(dentry)->lld_it) { + it = ll_d2d(dentry)->lld_it; + ll_d2d(dentry)->lld_it = NULL; + } else { + it = ll_convert_intent(&nd->intent.open, nd->flags); + if (IS_ERR(it)) + RETURN((struct dentry *)it); + } + + de = ll_lookup_it(parent, dentry, it, nd->flags); + if (de) + dentry = de; + if ((nd->flags & LOOKUP_OPEN) && !IS_ERR(dentry)) { /* Open */ + if (dentry->d_inode && + it_disposition(it, DISP_OPEN_OPEN)) { /* nocreate */ +#ifdef HAVE_FILE_IN_STRUCT_INTENT + if (S_ISFIFO(dentry->d_inode->i_mode)) { + // We cannot call open here as it would + // deadlock. + ptlrpc_req_finished( + (struct ptlrpc_request *) + it->d.lustre.it_data); + } else { + struct file *filp; + nd->intent.open.file->private_data = it; + filp =lookup_instantiate_filp(nd,dentry, + NULL); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)) +/* 2.6.1[456] have a bug in open_namei() that forgets to check + * nd->intent.open.file for error, so we need to return it as lookup's result + * instead */ + if (IS_ERR(filp)) { + if (de) + dput(de); + de = (struct dentry *) filp; + } +#endif + + } +#else /* HAVE_FILE_IN_STRUCT_INTENT */ + /* Release open handle as we have no way to + * pass it to ll_file_open */ + ll_release_openhandle(dentry, it); +#endif /* HAVE_FILE_IN_STRUCT_INTENT */ + } else if (it_disposition(it, DISP_OPEN_CREATE)) { + // XXX This can only reliably work on assumption + // that there are NO hashed negative dentries. + ll_d2d(dentry)->lld_it = it; + it = NULL; /* Will be freed in ll_create_nd */ + /* We absolutely depend on ll_create_nd to be + * called to not leak this intent and possible + * data attached to it */ + } + } + + if (it) { + ll_intent_release(it); + OBD_FREE(it, sizeof(*it)); + } + } else { + de = ll_lookup_it(parent, dentry, NULL, 0); + } + + RETURN(de); +} +#endif #endif /* We depend on "mode" being set with the proper file type/umask by now */ @@ -705,6 +830,40 @@ static int ll_mknod_generic(struct inode *dir, struct qstr *name, int mode, } #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#ifndef LUSTRE_KERNEL_VERSION +static int ll_create_nd(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) +{ + struct lookup_intent *it = ll_d2d(dentry)->lld_it; + int rc; + + if (!it) + return ll_mknod_generic(dir, &dentry->d_name, mode, 0, dentry); + + ll_d2d(dentry)->lld_it = NULL; + + /* Was there an error? Propagate it! */ + if (it->d.lustre.it_status) { + rc = it->d.lustre.it_status; + goto out; + } + + rc = ll_create_it(dir, dentry, mode, it); +#ifdef HAVE_FILE_IN_STRUCT_INTENT + if (nd && (nd->flags & LOOKUP_OPEN) && dentry->d_inode) { /* Open */ + nd->intent.open.file->private_data = it; + lookup_instantiate_filp(nd, dentry, NULL); + } +#else + ll_release_openhandle(dentry,it); +#endif + +out: + ll_intent_release(it); + OBD_FREE(it, sizeof(*it)); + + return rc; +} +#else static int ll_create_nd(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) { @@ -715,6 +874,7 @@ static int ll_create_nd(struct inode *dir, struct dentry *dentry, int mode, stru return ll_create_it(dir, dentry, mode, &nd->intent); } #endif +#endif static int ll_symlink_generic(struct inode *dir, struct qstr *name, const char *tgt) @@ -961,6 +1121,7 @@ static int ll_rename_generic(struct inode *src, struct qstr *src_name, RETURN(err); } +#ifdef LUSTRE_KERNEL_VERSION static int ll_mknod_raw(struct nameidata *nd, int mode, dev_t rdev) { return ll_mknod_generic(nd->dentry->d_inode, &nd->last, mode,rdev,NULL); @@ -991,6 +1152,7 @@ static int ll_unlink_raw(struct nameidata *nd) { return ll_unlink_generic(nd->dentry->d_inode, &nd->last); } +#endif static int ll_mknod(struct inode *dir, struct dentry *dchild, int mode, ll_dev_t rdev) @@ -1031,16 +1193,18 @@ static int ll_rename(struct inode *old_dir, struct dentry *old_dentry, #endif struct inode_operations ll_dir_inode_operations = { +#ifdef LUSTRE_KERNEL_VERSION .link_raw = ll_link_raw, .unlink_raw = ll_unlink_raw, .symlink_raw = ll_symlink_raw, .mkdir_raw = ll_mkdir_raw, .rmdir_raw = ll_rmdir_raw, .mknod_raw = ll_mknod_raw, - .mknod = ll_mknod, .rename_raw = ll_rename_raw, .setattr = ll_setattr, .setattr_raw = ll_setattr_raw, +#endif + .mknod = ll_mknod, #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) .create_it = ll_create_it, .lookup_it = ll_lookup_it, @@ -1048,7 +1212,6 @@ struct inode_operations ll_dir_inode_operations = { #else .lookup = ll_lookup_nd, .create = ll_create_nd, - .getattr_it = ll_getattr_it, /* We need all these non-raw things for NFSD, to not patch it. */ .unlink = ll_unlink, .mkdir = ll_mkdir, @@ -1067,10 +1230,12 @@ struct inode_operations ll_dir_inode_operations = { }; struct inode_operations ll_special_inode_operations = { +#ifdef LUSTRE_KERNEL_VERSION .setattr_raw = ll_setattr_raw, +#endif .setattr = ll_setattr, #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) - .getattr_it = ll_getattr_it, + .getattr = ll_getattr, #else .revalidate_it = ll_inode_revalidate_it, #endif diff --git a/lustre/llite/symlink.c b/lustre/llite/symlink.c index 3e5150e..aafb112 100644 --- a/lustre/llite/symlink.c +++ b/lustre/llite/symlink.c @@ -122,12 +122,23 @@ static int ll_follow_link(struct dentry *dentry, struct nameidata *nd) { struct inode *inode = dentry->d_inode; struct ll_inode_info *lli = ll_i2info(inode); +#ifdef LUSTRE_KERNEL_VERSION struct lookup_intent *it = ll_nd2it(nd); +#endif struct ptlrpc_request *request; int rc; char *symname; ENTRY; +#ifdef CONFIG_4KSTACKS + if (current->link_count >= 5) { + path_release(nd); /* Kernel assumes that ->follow_link() + releases nameidata on error */ + GOTO(out, rc = -ELOOP); + } +#endif + +#ifdef LUSTRE_KERNEL_VERSION if (it != NULL) { int op = it->it_op; int mode = it->it_create_mode; @@ -136,6 +147,7 @@ static int ll_follow_link(struct dentry *dentry, struct nameidata *nd) it->it_op = op; it->it_create_mode = mode; } +#endif CDEBUG(D_VFSTRACE, "VFS Op\n"); down(&lli->lli_open_sem); @@ -156,12 +168,14 @@ static int ll_follow_link(struct dentry *dentry, struct nameidata *nd) struct inode_operations ll_fast_symlink_inode_operations = { .readlink = ll_readlink, .setattr = ll_setattr, +#ifdef LUSTRE_KERNEL_VERSION .setattr_raw = ll_setattr_raw, +#endif .follow_link = ll_follow_link, #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) .revalidate_it = ll_inode_revalidate_it, #else - .getattr_it = ll_getattr_it, + .getattr = ll_getattr, #endif .permission = ll_inode_permission, .setxattr = ll_setxattr, diff --git a/lustre/llite/xattr.c b/lustre/llite/xattr.c index 3cc486b..559d9fa 100644 --- a/lustre/llite/xattr.c +++ b/lustre/llite/xattr.c @@ -23,12 +23,6 @@ #include #include #include -#ifdef HAVE_LINUX_XATTR_ACL_H -#include -#else -#define XATTR_NAME_ACL_ACCESS "system.posix_acl_access" -#define XATTR_NAME_ACL_DEFAULT "system.posix_acl_default" -#endif #define DEBUG_SUBSYSTEM S_LLITE @@ -37,6 +31,19 @@ #include #include +#ifndef POSIX_ACL_XATTR_ACCESS +#ifndef XATTR_NAME_ACL_ACCESS +#define XATTR_NAME_ACL_ACCESS "system.posix_acl_access" +#endif +#define POSIX_ACL_XATTR_ACCESS XATTR_NAME_ACL_ACCESS +#endif +#ifndef POSIX_ACL_XATTR_DEFAULT +#ifndef XATTR_NAME_ACL_DEFAULT +#define XATTR_NAME_ACL_DEFAULT "system.posix_acl_default" +#endif +#define POSIX_ACL_XATTR_DEFAULT XATTR_NAME_ACL_DEFAULT +#endif + #include "llite_internal.h" #define XATTR_USER_PREFIX "user." @@ -53,10 +60,10 @@ static int get_xattr_type(const char *name) { - if (!strcmp(name, XATTR_NAME_ACL_ACCESS)) + if (!strcmp(name, POSIX_ACL_XATTR_ACCESS)) return XATTR_ACL_ACCESS_T; - if (!strcmp(name, XATTR_NAME_ACL_DEFAULT)) + if (!strcmp(name, POSIX_ACL_XATTR_DEFAULT)) return XATTR_ACL_DEFAULT_T; if (!strncmp(name, XATTR_USER_PREFIX, diff --git a/lustre/lvfs/lvfs_linux.c b/lustre/lvfs/lvfs_linux.c index 969f1c3..42d6325 100644 --- a/lustre/lvfs/lvfs_linux.c +++ b/lustre/lvfs/lvfs_linux.c @@ -160,7 +160,7 @@ void push_ctxt(struct lvfs_run_ctxt *save, struct lvfs_run_ctxt *new_ctx, } current->fs->umask = 0; /* umask already applied on client */ set_fs(new_ctx->fs); - set_fs_pwd(current->fs, new_ctx->pwdmnt, new_ctx->pwd); + ll_set_fs_pwd(current->fs, new_ctx->pwdmnt, new_ctx->pwd); /* CDEBUG(D_INFO, @@ -200,7 +200,7 @@ void pop_ctxt(struct lvfs_run_ctxt *saved, struct lvfs_run_ctxt *new_ctx, current->fs->pwdmnt, new_ctx->pwdmnt); set_fs(saved->fs); - set_fs_pwd(current->fs, saved->pwdmnt, saved->pwd); + ll_set_fs_pwd(current->fs, saved->pwdmnt, saved->pwd); dput(saved->pwd); mntput(saved->pwdmnt); @@ -425,6 +425,7 @@ EXPORT_SYMBOL(l_readdir); EXPORT_SYMBOL(obd_memory); EXPORT_SYMBOL(obd_memmax); +#ifdef LUSTRE_KERNEL_VERSION #ifdef HAVE_OLD_DEV_SET_RDONLY void dev_set_rdonly(lvfs_sbdev_type dev, int no_write); void dev_clear_rdonly(int no_write); @@ -471,6 +472,7 @@ void lvfs_clear_rdonly(lvfs_sbdev_type dev) EXPORT_SYMBOL(lvfs_set_rdonly); EXPORT_SYMBOL(lvfs_check_rdonly); EXPORT_SYMBOL(lvfs_clear_rdonly); +#endif int lvfs_check_io_health(struct obd_device *obd, struct file *file) { diff --git a/lustre/mdc/mdc_lib.c b/lustre/mdc/mdc_lib.c index eb503c4..acfb08d 100644 --- a/lustre/mdc/mdc_lib.c +++ b/lustre/mdc/mdc_lib.c @@ -195,7 +195,6 @@ void mdc_setattr_pack(struct ptlrpc_request *req, int offset, rec->sa_ctime = LTIME_S(iattr->ia_ctime); rec->sa_attr_flags = ((struct ll_iattr_struct *)iattr)->ia_attr_flags; - if ((iattr->ia_valid & ATTR_GID) && in_group_p(iattr->ia_gid)) rec->sa_suppgid = iattr->ia_gid; else diff --git a/lustre/ptlrpc/service.c b/lustre/ptlrpc/service.c index 699c322..0652bbc 100644 --- a/lustre/ptlrpc/service.c +++ b/lustre/ptlrpc/service.c @@ -836,7 +836,7 @@ void ptlrpc_daemonize(char *name) cfs_daemonize(name); exit_fs(cfs_current()); current->fs = fs; - set_fs_pwd(current->fs, init_task.fs->pwdmnt, init_task.fs->pwd); + ll_set_fs_pwd(current->fs, init_task.fs->pwdmnt, init_task.fs->pwd); } static void -- 1.8.3.1