X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;ds=sidebyside;f=lustre%2Fllite%2Fnamei.c;h=81bf255d52949ee8f37c451a5b6a70ecb8639f5e;hb=a1052417b78bc18898161c4ed44d79de4a1a2f23;hp=84e8f73c368df83b799eee686f44509b9d5434fd;hpb=867a0e5591ababddff68e451580ab1accee2ea4d;p=fs%2Flustre-release.git diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index 84e8f73..81bf255 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -27,7 +27,7 @@ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * - * Copyright (c) 2011, 2012, Whamcloud, Inc. + * Copyright (c) 2011, 2013, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -51,6 +51,9 @@ #include #include "llite_internal.h" +static int ll_create_it(struct inode *, struct dentry *, + int, struct lookup_intent *); + /* * Check if we have something mounted at the named dchild. * In such a case there would always be dentry present. @@ -147,10 +150,14 @@ struct inode *ll_iget(struct super_block *sb, ino_t hash, ll_read_inode2(inode, md); if (S_ISREG(inode->i_mode) && - ll_i2info(inode)->lli_clob == NULL) + ll_i2info(inode)->lli_clob == NULL) { + CDEBUG(D_INODE, + "%s: apply lsm %p to inode "DFID".\n", + ll_get_fsname(sb, NULL, 0), md->lsm, + PFID(ll_inode2fid(inode))); rc = cl_file_inode_init(inode, md); + } if (rc != 0) { - md->lsm = NULL; make_bad_inode(inode); unlock_new_inode(inode); iput(inode); @@ -168,9 +175,10 @@ struct inode *ll_iget(struct super_block *sb, ino_t hash, static void ll_invalidate_negative_children(struct inode *dir) { struct dentry *dentry, *tmp_subdir; + struct ll_d_hlist_node *p; ll_lock_dcache(dir); - list_for_each_entry(dentry, &dir->i_dentry, d_alias) { + ll_d_hlist_for_each_entry(dentry, p, &dir->i_dentry, d_alias) { spin_lock(&dentry->d_lock); if (!list_empty(&dentry->d_subdirs)) { struct dentry *child; @@ -179,7 +187,7 @@ static void ll_invalidate_negative_children(struct inode *dir) &dentry->d_subdirs, d_u.d_child) { if (child->d_inode == NULL) - d_lustre_invalidate(child); + d_lustre_invalidate(child, 1); } } spin_unlock(&dentry->d_lock); @@ -197,19 +205,23 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, switch (flag) { case LDLM_CB_BLOCKING: ldlm_lock2handle(lock, &lockh); - rc = ldlm_cli_cancel(&lockh); + rc = ldlm_cli_cancel(&lockh, LCF_ASYNC); if (rc < 0) { CDEBUG(D_INODE, "ldlm_cli_cancel: %d\n", rc); RETURN(rc); } break; case LDLM_CB_CANCELING: { - struct inode *inode = ll_inode_from_lock(lock); + struct inode *inode = ll_inode_from_resource_lock(lock); struct ll_inode_info *lli; __u64 bits = lock->l_policy_data.l_inodebits.bits; struct lu_fid *fid; ldlm_mode_t mode = lock->l_req_mode; + /* Inode is set to lock->l_resource->lr_lvb_inode + * for mdc - bug 24555 */ + LASSERT(lock->l_ast_data == NULL); + /* Invalidate all dentries associated with this inode */ if (inode == NULL) break; @@ -218,19 +230,16 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, /* For OPEN locks we differentiate between lock modes * LCK_CR, LCK_CW, LCK_PR - bug 22891 */ if (bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_UPDATE | - MDS_INODELOCK_LAYOUT)) + MDS_INODELOCK_LAYOUT | MDS_INODELOCK_PERM)) ll_have_md_lock(inode, &bits, LCK_MINMODE); if (bits & MDS_INODELOCK_OPEN) ll_have_md_lock(inode, &bits, mode); - fid = ll_inode2fid(inode); - if (lock->l_resource->lr_name.name[0] != fid_seq(fid) || - lock->l_resource->lr_name.name[1] != fid_oid(fid) || - lock->l_resource->lr_name.name[2] != fid_ver(fid)) { - LDLM_ERROR(lock, "data mismatch with object " - DFID" (%p)", PFID(fid), inode); - } + fid = ll_inode2fid(inode); + if (!fid_res_name_eq(fid, &lock->l_resource->lr_name)) + LDLM_ERROR(lock, "data mismatch with object " + DFID" (%p)", PFID(fid), inode); if (bits & MDS_INODELOCK_OPEN) { int flags = 0; @@ -254,15 +263,20 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, lli = ll_i2info(inode); if (bits & MDS_INODELOCK_LAYOUT) { - struct cl_object_conf conf = { .coc_inode = inode, - .coc_invalidate = true }; + struct cl_object_conf conf = { { 0 } }; + + conf.coc_opc = OBJECT_CONF_INVALIDATE; + conf.coc_inode = inode; rc = ll_layout_conf(inode, &conf); if (rc) CDEBUG(D_INODE, "invaliding layout %d.\n", rc); } - if (bits & MDS_INODELOCK_UPDATE) + if (bits & MDS_INODELOCK_UPDATE) { + spin_lock(&lli->lli_lock); lli->lli_flags &= ~LLIF_MDS_SIZE_LOCK; + spin_unlock(&lli->lli_lock); + } if (S_ISDIR(inode->i_mode) && (bits & MDS_INODELOCK_UPDATE)) { @@ -274,7 +288,7 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, if (inode->i_sb->s_root && inode != inode->i_sb->s_root->d_inode && - (bits & MDS_INODELOCK_LOOKUP)) + (bits & (MDS_INODELOCK_LOOKUP | MDS_INODELOCK_PERM))) ll_invalidate_aliases(inode); iput(inode); break; @@ -342,14 +356,15 @@ void ll_i2gids(__u32 *suppgids, struct inode *i1, struct inode *i2) static struct dentry *ll_find_alias(struct inode *inode, struct dentry *dentry) { struct dentry *alias, *discon_alias, *invalid_alias; + struct ll_d_hlist_node *p; - if (list_empty(&inode->i_dentry)) + if (ll_d_hlist_empty(&inode->i_dentry)) return NULL; discon_alias = invalid_alias = NULL; ll_lock_dcache(inode); - list_for_each_entry(alias, &inode->i_dentry, d_alias) { + ll_d_hlist_for_each_entry(alias, p, &inode->i_dentry, d_alias) { LASSERT(alias != dentry); spin_lock(&alias->d_lock); @@ -379,7 +394,7 @@ static struct dentry *ll_find_alias(struct inode *inode, struct dentry *dentry) } /* - * Similar to d_splice_alias(), but lustre treats DCACHE_LUSTRE_INVALID alias + * Similar to d_splice_alias(), but lustre treats invalid alias * similar to DCACHE_DISCONNECTED, and tries to use it anyway. */ struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de) @@ -398,8 +413,8 @@ struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de) return new; } } - __d_lustre_invalidate(de); ll_dops_init(de, 1, 1); + __d_lustre_invalidate(de); d_add(de, inode); CDEBUG(D_DENTRY, "Add dentry %p inode %p refc %d flags %#x\n", de, de->d_inode, d_refcount(de), de->d_flags); @@ -419,8 +434,10 @@ int ll_lookup_it_finish(struct ptlrpc_request *request, /* NB 1 request reference will be taken away by ll_intent_lock() * when I return */ + CDEBUG(D_DENTRY, "it %p it_disposition %x\n", it, + it->d.lustre.it_disposition); if (!it_disposition(it, DISP_LOOKUP_NEG)) { - rc = ll_prep_inode(&inode, request, (*de)->d_sb); + rc = ll_prep_inode(&inode, request, (*de)->d_sb, it); if (rc) RETURN(rc); @@ -436,13 +453,21 @@ int ll_lookup_it_finish(struct ptlrpc_request *request, Also see bug 7198. */ } - *de = ll_splice_alias(inode, *de); + /* Only hash *de if it is unhashed (new dentry). + * Atoimc_open may passin hashed dentries for open. + */ + if (d_unhashed(*de)) + *de = ll_splice_alias(inode, *de); if (!it_disposition(it, DISP_LOOKUP_NEG)) { /* we have lookup look - unhide dentry */ if (bits & MDS_INODELOCK_LOOKUP) d_lustre_revalidate(*de); - } else { + } else if (!it_disposition(it, DISP_OPEN_CREATE)) { + /* If file created on server, don't depend on parent UPDATE + * lock to unhide it. It is left hidden and next lookup can + * find it in ll_splice_alias. + */ /* Check that parent has UPDATE lock. */ struct lookup_intent parent_it = { .it_op = IT_GETATTR, @@ -516,7 +541,9 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, if (IS_ERR(op_data)) RETURN((void *)op_data); - it->it_create_mode &= ~cfs_curproc_umask(); + /* enforce umask if acl disabled or MDS doesn't support umask */ + if (!IS_POSIXACL(parent) || !exp_connect_umask(ll_i2mdexp(parent))) + it->it_create_mode &= ~cfs_curproc_umask(); rc = md_intent_lock(ll_i2mdexp(parent), op_data, NULL, 0, it, lookup_flags, &req, ll_md_blocking_ast, 0); @@ -549,6 +576,121 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, return retval; } +#ifdef HAVE_IOP_ATOMIC_OPEN +static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry, + unsigned int flags) +{ + struct lookup_intent *itp, it = { .it_op = IT_GETATTR }; + struct dentry *de; + + CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p),flags=%u\n", + dentry->d_name.len, dentry->d_name.name, parent->i_ino, + parent->i_generation, parent, flags); + + /* Optimize away (CREATE && !OPEN). Let .create handle the race. */ + if ((flags & LOOKUP_CREATE ) && !(flags & LOOKUP_OPEN)) { + ll_dops_init(dentry, 1, 1); + __d_lustre_invalidate(dentry); + d_add(dentry, NULL); + return NULL; + } + + if (flags & (LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE)) + itp = NULL; + else + itp = ⁢ + de = ll_lookup_it(parent, dentry, itp, 0); + + if (itp != NULL) + ll_intent_release(itp); + + return de; +} + +/* + * For cached negative dentry and new dentry, handle lookup/create/open + * together. + */ +static int ll_atomic_open(struct inode *dir, struct dentry *dentry, + struct file *file, unsigned open_flags, + umode_t mode, int *opened) +{ + struct lookup_intent *it; + struct dentry *de; + long long lookup_flags = LOOKUP_OPEN; + int rc = 0; + ENTRY; + + CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p),file %p," + "open_flags %x,mode %x opened %d\n", + dentry->d_name.len, dentry->d_name.name, dir->i_ino, + dir->i_generation, dir, file, open_flags, mode, *opened); + + OBD_ALLOC(it, sizeof(*it)); + if (!it) + RETURN(-ENOMEM); + + it->it_op = IT_OPEN; + if (mode) { + it->it_op |= IT_CREAT; + lookup_flags |= LOOKUP_CREATE; + } + it->it_create_mode = (mode & S_IALLUGO) | S_IFREG; + it->it_flags = (open_flags & ~O_ACCMODE) | OPEN_FMODE(open_flags); + + /* Dentry added to dcache tree in ll_lookup_it */ + de = ll_lookup_it(dir, dentry, it, lookup_flags); + if (IS_ERR(de)) + rc = PTR_ERR(de); + else if (de != NULL) + dentry = de; + + if (!rc) { + if (it_disposition(it, DISP_OPEN_CREATE)) { + /* Dentry instantiated in ll_create_it. */ + rc = ll_create_it(dir, dentry, mode, it); + if (rc) { + /* We dget in ll_splice_alias. */ + if (de != NULL) + dput(de); + goto out_release; + } + + *opened |= FILE_CREATED; + } + if (dentry->d_inode && it_disposition(it, DISP_OPEN_OPEN)) { + /* Open dentry. */ + if (S_ISFIFO(dentry->d_inode->i_mode)) { + /* We cannot call open here as it would + * deadlock. + */ + if (it_disposition(it, DISP_ENQ_OPEN_REF)) + ptlrpc_req_finished( + (struct ptlrpc_request *) + it->d.lustre.it_data); + rc = finish_no_open(file, de); + } else { + file->private_data = it; + rc = finish_open(file, dentry, NULL, opened); + /* We dget in ll_splice_alias. finish_open takes + * care of dget for fd open. + */ + if (de != NULL) + dput(de); + } + } else { + rc = finish_no_open(file, de); + } + } + +out_release: + ll_intent_release(it); + OBD_FREE(it, sizeof(*it)); + + RETURN(rc); +} + +#else /* !HAVE_IOP_ATOMIC_OPEN */ struct lookup_intent *ll_convert_intent(struct open_intent *oit, int lookup_flags) { @@ -643,6 +785,7 @@ static struct dentry *ll_lookup_nd(struct inode *parent, struct dentry *dentry, RETURN(de); } +#endif /* HAVE_IOP_ATOMIC_OPEN */ /* We depend on "mode" being set with the proper file type/umask by now */ static struct inode *ll_create_node(struct inode *dir, const char *name, @@ -661,11 +804,11 @@ static struct inode *ll_create_node(struct inode *dir, const char *name, LASSERT(it_disposition(it, DISP_ENQ_CREATE_REF)); request = it->d.lustre.it_data; it_clear_disposition(it, DISP_ENQ_CREATE_REF); - rc = ll_prep_inode(&inode, request, dir->i_sb); + rc = ll_prep_inode(&inode, request, dir->i_sb, it); if (rc) GOTO(out, inode = ERR_PTR(rc)); - LASSERT(list_empty(&inode->i_dentry)); + LASSERT(ll_d_hlist_empty(&inode->i_dentry)); /* We asked for a lock on the directory, but were granted a * lock on the inode. Since we finally have an inode pointer, @@ -694,27 +837,30 @@ static struct inode *ll_create_node(struct inode *dir, const char *name, * with d_instantiate(). */ static int ll_create_it(struct inode *dir, struct dentry *dentry, int mode, - struct lookup_intent *it) + struct lookup_intent *it) { - struct inode *inode; - int rc = 0; - ENTRY; + struct inode *inode; + int rc = 0; + ENTRY; - CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p),intent=%s\n", - dentry->d_name.len, dentry->d_name.name, dir->i_ino, - dir->i_generation, dir, LL_IT2STR(it)); + CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p),intent=%s\n", + dentry->d_name.len, dentry->d_name.name, dir->i_ino, + dir->i_generation, dir, LL_IT2STR(it)); - rc = it_open_error(DISP_OPEN_CREATE, it); - if (rc) - RETURN(rc); + rc = it_open_error(DISP_OPEN_CREATE, it); + if (rc) + RETURN(rc); - inode = ll_create_node(dir, dentry->d_name.name, dentry->d_name.len, - NULL, 0, mode, 0, it); - if (IS_ERR(inode)) - RETURN(PTR_ERR(inode)); + inode = ll_create_node(dir, dentry->d_name.name, dentry->d_name.len, + NULL, 0, mode, 0, it); + if (IS_ERR(inode)) + RETURN(PTR_ERR(inode)); - d_instantiate(dentry, inode); - RETURN(0); + if (filename_is_volatile(dentry->d_name.name, dentry->d_name.len, NULL)) + ll_i2info(inode)->lli_volatile = true; + + d_instantiate(dentry, inode); + RETURN(0); } static void ll_update_times(struct ptlrpc_request *request, @@ -765,7 +911,7 @@ static int ll_new_node(struct inode *dir, struct qstr *name, ll_update_times(request, dir); if (dchild) { - err = ll_prep_inode(&inode, request, dchild->d_sb); + err = ll_prep_inode(&inode, request, dchild->d_sb, NULL); if (err) GOTO(err_exit, err); @@ -788,7 +934,8 @@ static int ll_mknod_generic(struct inode *dir, struct qstr *name, int mode, name->len, name->name, dir->i_ino, dir->i_generation, dir, mode, rdev); - mode &= ~cfs_curproc_umask(); + if (!IS_POSIXACL(dir) || !exp_connect_umask(ll_i2mdexp(dir))) + mode &= ~cfs_curproc_umask(); switch (mode & S_IFMT) { case 0: @@ -814,8 +961,32 @@ static int ll_mknod_generic(struct inode *dir, struct qstr *name, int mode, RETURN(err); } +#ifdef HAVE_IOP_ATOMIC_OPEN +/* + * Plain create. Intent create is handled in atomic_open. + */ +static int ll_create_nd(struct inode *dir, struct dentry *dentry, + umode_t mode, bool want_excl) +{ + int rc; + + CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p)," + "flags=%u, excl=%d\n", + dentry->d_name.len, dentry->d_name.name, dir->i_ino, + dir->i_generation, dir, mode, want_excl); + + rc = ll_mknod_generic(dir, &dentry->d_name, mode, 0, dentry); + + ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_CREATE, 1); + + CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s, unhashed %d\n", + dentry->d_name.len, dentry->d_name.name, d_unhashed(dentry)); + + return rc; +} +#else /* !HAVE_IOP_ATOMIC_OPEN */ static int ll_create_nd(struct inode *dir, struct dentry *dentry, - int mode, struct nameidata *nd) + ll_umode_t mode, struct nameidata *nd) { struct lookup_intent *it = ll_d2d(dentry)->lld_it; int rc; @@ -850,6 +1021,7 @@ out: return rc; } +#endif /* HAVE_IOP_ATOMIC_OPEN */ static int ll_symlink_generic(struct inode *dir, struct qstr *name, const char *tgt, struct dentry *dchild) @@ -912,7 +1084,9 @@ static int ll_mkdir_generic(struct inode *dir, struct qstr *name, CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p)\n", name->len, name->name, dir->i_ino, dir->i_generation, dir); - mode = (mode & (S_IRWXUGO|S_ISVTX) & ~cfs_curproc_umask()) | S_IFDIR; + if (!IS_POSIXACL(dir) || !exp_connect_umask(ll_i2mdexp(dir))) + mode &= ~cfs_curproc_umask(); + mode = (mode & (S_IRWXUGO|S_ISVTX)) | S_IFDIR; err = ll_new_node(dir, name, NULL, mode, 0, dchild, LUSTRE_OPC_MKDIR); if (!err) @@ -926,10 +1100,10 @@ static int ll_mkdir_generic(struct inode *dir, struct qstr *name, static void ll_get_child_fid(struct inode * dir, struct qstr *name, struct lu_fid *fid) { - struct dentry *parent, *child; + struct dentry *parent, *child; - parent = list_entry(dir->i_dentry.next, struct dentry, d_alias); - child = d_lookup(parent, name); + parent = ll_d_hlist_entry(dir->i_dentry, struct dentry, d_alias); + child = d_lookup(parent, name); if (child) { if (child->d_inode) *fid = *ll_inode2fid(child->d_inode); @@ -957,6 +1131,7 @@ static int ll_rmdir_generic(struct inode *dir, struct dentry *dparent, RETURN(PTR_ERR(op_data)); ll_get_child_fid(dir, name, &op_data->op_fid3); + op_data->op_fid2 = op_data->op_fid3; rc = md_unlink(ll_i2sbi(dir)->ll_md_exp, op_data, &request); ll_finish_md_op_data(op_data); if (rc == 0) { @@ -968,6 +1143,35 @@ static int ll_rmdir_generic(struct inode *dir, struct dentry *dparent, RETURN(rc); } +/** + * Remove dir entry + **/ +int ll_rmdir_entry(struct inode *dir, char *name, int namelen) +{ + struct ptlrpc_request *request = NULL; + struct md_op_data *op_data; + int rc; + ENTRY; + + CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p)\n", + namelen, name, dir->i_ino, dir->i_generation, dir); + + op_data = ll_prep_md_op_data(NULL, dir, NULL, name, strlen(name), + S_IFDIR, LUSTRE_OPC_ANY, NULL); + if (IS_ERR(op_data)) + RETURN(PTR_ERR(op_data)); + op_data->op_cli_flags |= CLI_RM_ENTRY; + rc = md_unlink(ll_i2sbi(dir)->ll_md_exp, op_data, &request); + ll_finish_md_op_data(op_data); + if (rc == 0) { + ll_update_times(request, dir); + ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_RMDIR, 1); + } + + ptlrpc_req_finished(request); + RETURN(rc); +} + int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir) { struct mdt_body *body; @@ -1008,8 +1212,7 @@ int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir) if (oa == NULL) GOTO(out_free_memmd, rc = -ENOMEM); - oa->o_id = lsm->lsm_object_id; - oa->o_seq = lsm->lsm_object_seq; + oa->o_oi = lsm->lsm_oi; oa->o_mode = body->mode & S_IFMT; oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLGROUP; @@ -1032,17 +1235,17 @@ int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir) GOTO(out_free_memmd, rc); } - rc = obd_destroy(NULL, ll_i2dtexp(dir), oa, lsm, &oti, - ll_i2mdexp(dir), oc); - capa_put(oc); - OBDO_FREE(oa); - if (rc) - CERROR("obd destroy objid "LPX64" error %d\n", - lsm->lsm_object_id, rc); - out_free_memmd: - obd_free_memmd(ll_i2dtexp(dir), &lsm); - out: - return rc; + rc = obd_destroy(NULL, ll_i2dtexp(dir), oa, lsm, &oti, + ll_i2mdexp(dir), oc); + capa_put(oc); + if (rc) + CERROR("obd destroy objid "DOSTID" error %d\n", + POSTID(&lsm->lsm_oi), rc); +out_free_memmd: + obd_free_memmd(ll_i2dtexp(dir), &lsm); + OBDO_FREE(oa); +out: + return rc; } /* ll_unlink_generic() doesn't update the inode with the new link count. @@ -1071,11 +1274,12 @@ static int ll_unlink_generic(struct inode *dir, struct dentry *dparent, if (IS_ERR(op_data)) RETURN(PTR_ERR(op_data)); - ll_get_child_fid(dir, name, &op_data->op_fid3); - rc = md_unlink(ll_i2sbi(dir)->ll_md_exp, op_data, &request); - ll_finish_md_op_data(op_data); - if (rc) - GOTO(out, rc); + ll_get_child_fid(dir, name, &op_data->op_fid3); + op_data->op_fid2 = op_data->op_fid3; + rc = md_unlink(ll_i2sbi(dir)->ll_md_exp, op_data, &request); + ll_finish_md_op_data(op_data); + if (rc) + GOTO(out, rc); ll_update_times(request, dir); ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_UNLINK, 1); @@ -1128,7 +1332,7 @@ static int ll_rename_generic(struct inode *src, struct dentry *src_dparent, RETURN(err); } -static int ll_mknod(struct inode *dir, struct dentry *dchild, int mode, +static int ll_mknod(struct inode *dir, struct dentry *dchild, ll_umode_t mode, dev_t rdev) { return ll_mknod_generic(dir, &dchild->d_name, mode, @@ -1139,25 +1343,30 @@ static int ll_unlink(struct inode * dir, struct dentry *dentry) { return ll_unlink_generic(dir, NULL, dentry, &dentry->d_name); } -static int ll_mkdir(struct inode *dir, struct dentry *dentry, int mode) + +static int ll_mkdir(struct inode *dir, struct dentry *dentry, ll_umode_t mode) { return ll_mkdir_generic(dir, &dentry->d_name, mode, dentry); } + static int ll_rmdir(struct inode *dir, struct dentry *dentry) { return ll_rmdir_generic(dir, NULL, dentry, &dentry->d_name); } + static int ll_symlink(struct inode *dir, struct dentry *dentry, const char *oldname) { return ll_symlink_generic(dir, &dentry->d_name, oldname, dentry); } + static int ll_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) { return ll_link_generic(old_dentry->d_inode, dir, &new_dentry->d_name, new_dentry); } + static int ll_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { @@ -1177,6 +1386,9 @@ static int ll_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode_operations ll_dir_inode_operations = { .mknod = ll_mknod, +#ifdef HAVE_IOP_ATOMIC_OPEN + .atomic_open = ll_atomic_open, +#endif .lookup = ll_lookup_nd, .create = ll_create_nd, /* We need all these non-raw things for NFSD, to not patch it. */