[])
])
+AC_DEFUN([LC_STRUCT_INTENT_FILE],
+[AC_MSG_CHECKING([if struct open_intent has a file field])
+LB_LINUX_TRY_COMPILE([
+ #include <linux/fs.h>
+ #include <linux/namei.h>
+],[
+ 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 <linux/posix_acl_xattr.h>
+ ],[],[
+ 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
#
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
])
#
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
#include <libcfs/linux/portals_compat25.h>
+#include <linux/lustre_patchless_compat.h>
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
struct ll_iattr_struct {
struct iattr iattr;
#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)
--- /dev/null
+#ifndef LUSTRE_INTENT_H
+#define LUSTRE_INTENT_H
+
+#include <linux/lustre_version.h>
+
+#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
#ifdef __KERNEL__
# include <linux/fs.h>
# include <linux/dcache.h>
-
-#ifdef HAVE_XATTR_ACL
-#include <linux/xattr_acl.h>
-#else
-#include <linux/posix_acl_xattr.h>
-#endif
+# ifdef CONFIG_FS_POSIX_ACL
+# ifdef HAVE_XATTR_ACL
+# include <linux/xattr_acl.h>
+# endif
+# ifdef HAVE_LINUX_POSIX_ACL_XATTR_H
+# include <linux/posix_acl_xattr.h>
+# endif
+# endif
+# ifndef LUSTRE_KERNEL_VERSION
+# include <linux/lustre_intent.h>
+# endif
#endif
struct ldlm_lock_desc;
--- /dev/null
+#ifndef LUSTRE_PATCHLESS_COMPAT_H
+#define LUSTRE_PATCHLESS_COMPAT_H
+
+#include <linux/lustre_version.h>
+#ifndef LUSTRE_KERNEL_VERSION
+#include <linux/fs.h>
+
+#ifndef HAVE_TRUNCATE_COMPLETE_PAGE
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/hash.h>
+
+/* 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
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
+#include <linux/namei.h>
#include <linux/sched.h>
#include <lvfs.h>
#ifdef __KERNEL__
# include <libcfs/libcfs.h>
+# include <linux/lustre_intent.h>
#else
# include <liblustre.h>
# include <libcfs/kp30.h>
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));
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.
*
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);
}
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);
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 "
/* 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) {
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);
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,
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);
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);
&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) {
GOTO(out, rc = 0);
}
+revalidate_finish:
rc = revalidate_it_finish(req, DLM_REPLY_REC_OFF, it, de);
if (rc != 0) {
ll_intent_release(it);
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)
}
#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;
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 = {
#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,
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)
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;
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
#ifdef CONFIG_FS_POSIX_ACL
# include <linux/fs.h>
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
-#include <linux/posix_acl_xattr.h>
-#else
-#include <linux/xattr_acl.h>
+#ifdef HAVE_XATTR_ACL
+# include <linux/xattr_acl.h>
+#endif
+#ifdef HAVE_LINUX_POSIX_ACL_XATTR_H
+# include <linux/posix_acl_xattr.h>
#endif
#endif
__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)
#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))
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)
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);
}
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)
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);
} 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);
}
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;
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;
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);
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;
}
}
#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)
{
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 */
}
#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)
{
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)
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);
{
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)
#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,
#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,
};
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
{
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;
it->it_op = op;
it->it_create_mode = mode;
}
+#endif
CDEBUG(D_VFSTRACE, "VFS Op\n");
down(&lli->lli_open_sem);
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,
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp_lock.h>
-#ifdef HAVE_LINUX_XATTR_ACL_H
-#include <linux/xattr_acl.h>
-#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
#include <lustre_dlm.h>
#include <linux/lustre_version.h>
+#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."
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,
}
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,
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);
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);
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)
{
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
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