diff options
33 files changed, 488 insertions, 465 deletions
diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl index cb713df81180..b30dd8154cc2 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -384,3 +384,5 @@ 375 i386 membarrier sys_membarrier 376 i386 mlock2 sys_mlock2 377 i386 copy_file_range sys_copy_file_range +378 i386 preadv2 sys_preadv2 +379 i386 pwritev2 sys_pwritev2 diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index dc1040a50bdc..31cec929eb8d 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -333,6 +333,8 @@ 324 common membarrier sys_membarrier 325 common mlock2 sys_mlock2 326 common copy_file_range sys_copy_file_range +327 64 preadv2 sys_preadv2 +328 64 pwritev2 sys_pwritev2 # # x32-specific system call numbers start at 512 to avoid cache impact diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index c6d7d3dbd52a..75dd739ac3e6 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -537,8 +537,6 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, u ino->dentry = dentry; autofs4_add_active(dentry); - - d_instantiate(dentry, NULL); } return NULL; } diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c index 452e98dd7560..1ee54ffd3a24 100644 --- a/fs/cachefiles/daemon.c +++ b/fs/cachefiles/daemon.c @@ -162,6 +162,8 @@ static ssize_t cachefiles_daemon_read(struct file *file, char __user *_buffer, size_t buflen, loff_t *pos) { struct cachefiles_cache *cache = file->private_data; + unsigned long long b_released; + unsigned f_released; char buffer[256]; int n; @@ -174,6 +176,8 @@ static ssize_t cachefiles_daemon_read(struct file *file, char __user *_buffer, cachefiles_has_space(cache, 0, 0); /* summarise */ + f_released = atomic_xchg(&cache->f_released, 0); + b_released = atomic_long_xchg(&cache->b_released, 0); clear_bit(CACHEFILES_STATE_CHANGED, &cache->flags); n = snprintf(buffer, sizeof(buffer), @@ -183,15 +187,18 @@ static ssize_t cachefiles_daemon_read(struct file *file, char __user *_buffer, " fstop=%llx" " brun=%llx" " bcull=%llx" - " bstop=%llx", + " bstop=%llx" + " freleased=%x" + " breleased=%llx", test_bit(CACHEFILES_CULLING, &cache->flags) ? '1' : '0', (unsigned long long) cache->frun, (unsigned long long) cache->fcull, (unsigned long long) cache->fstop, (unsigned long long) cache->brun, (unsigned long long) cache->bcull, - (unsigned long long) cache->bstop - ); + (unsigned long long) cache->bstop, + f_released, + b_released); if (n > buflen) return -EMSGSIZE; diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index 675a3332d72f..861d611b8c05 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c @@ -291,15 +291,8 @@ static void cachefiles_drop_object(struct fscache_object *_object) } /* note that the object is now inactive */ - if (test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)) { - write_lock(&cache->active_lock); - if (!test_and_clear_bit(CACHEFILES_OBJECT_ACTIVE, - &object->flags)) - BUG(); - rb_erase(&object->active_node, &cache->active_nodes); - wake_up_bit(&object->flags, CACHEFILES_OBJECT_ACTIVE); - write_unlock(&cache->active_lock); - } + if (test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)) + cachefiles_mark_object_inactive(cache, object); dput(object->dentry); object->dentry = NULL; diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h index 9c4b737a54df..2fcde1a34b7c 100644 --- a/fs/cachefiles/internal.h +++ b/fs/cachefiles/internal.h @@ -66,6 +66,8 @@ struct cachefiles_cache { struct rb_root active_nodes; /* active nodes (can't be culled) */ rwlock_t active_lock; /* lock for active_nodes */ atomic_t gravecounter; /* graveyard uniquifier */ + atomic_t f_released; /* number of objects released lately */ + atomic_long_t b_released; /* number of blocks released lately */ unsigned frun_percent; /* when to stop culling (% files) */ unsigned fcull_percent; /* when to start culling (% files) */ unsigned fstop_percent; /* when to stop allocating (% files) */ @@ -157,6 +159,8 @@ extern char *cachefiles_cook_key(const u8 *raw, int keylen, uint8_t type); /* * namei.c */ +extern void cachefiles_mark_object_inactive(struct cachefiles_cache *cache, + struct cachefiles_object *object); extern int cachefiles_delete_object(struct cachefiles_cache *cache, struct cachefiles_object *object); extern int cachefiles_walk_to_object(struct cachefiles_object *parent, diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index 1c2334c163dd..4ae75006e73b 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c @@ -258,6 +258,28 @@ requeue: } /* + * Mark an object as being inactive. + */ +void cachefiles_mark_object_inactive(struct cachefiles_cache *cache, + struct cachefiles_object *object) +{ + write_lock(&cache->active_lock); + rb_erase(&object->active_node, &cache->active_nodes); + clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags); + write_unlock(&cache->active_lock); + + wake_up_bit(&object->flags, CACHEFILES_OBJECT_ACTIVE); + + /* This object can now be culled, so we need to let the daemon know + * that there is something it can remove if it needs to. + */ + atomic_long_add(d_backing_inode(object->dentry)->i_blocks, + &cache->b_released); + if (atomic_inc_return(&cache->f_released)) + cachefiles_state_changed(cache); +} + +/* * delete an object representation from the cache * - file backed objects are unlinked * - directory backed objects are stuffed into the graveyard for userspace to @@ -684,11 +706,7 @@ mark_active_timed_out: check_error: _debug("check error %d", ret); - write_lock(&cache->active_lock); - rb_erase(&object->active_node, &cache->active_nodes); - clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags); - wake_up_bit(&object->flags, CACHEFILES_OBJECT_ACTIVE); - write_unlock(&cache->active_lock); + cachefiles_mark_object_inactive(cache, object); release_dentry: dput(object->dentry); object->dentry = NULL; diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index fb4ba2e4e2a5..be2d87f33177 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -975,13 +975,8 @@ out_unlock: /* * splice a dentry to an inode. * caller must hold directory i_mutex for this to be safe. - * - * we will only rehash the resulting dentry if @prehash is - * true; @prehash will be set to false (for the benefit of - * the caller) if we fail. */ -static struct dentry *splice_dentry(struct dentry *dn, struct inode *in, - bool *prehash) +static struct dentry *splice_dentry(struct dentry *dn, struct inode *in) { struct dentry *realdn; @@ -994,8 +989,6 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in, if (IS_ERR(realdn)) { pr_err("splice_dentry error %ld %p inode %p ino %llx.%llx\n", PTR_ERR(realdn), dn, in, ceph_vinop(in)); - if (prehash) - *prehash = false; /* don't rehash on error */ dn = realdn; /* note realdn contains the error */ goto out; } else if (realdn) { @@ -1011,8 +1004,6 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in, dout("dn %p attached to %p ino %llx.%llx\n", dn, d_inode(dn), ceph_vinop(d_inode(dn))); } - if ((!prehash || *prehash) && d_unhashed(dn)) - d_rehash(dn); out: return dn; } @@ -1245,10 +1236,8 @@ retry_lookup: dout("d_delete %p\n", dn); d_delete(dn); } else { - dout("d_instantiate %p NULL\n", dn); - d_instantiate(dn, NULL); if (have_lease && d_unhashed(dn)) - d_rehash(dn); + d_add(dn, NULL); update_dentry_lease(dn, rinfo->dlease, session, req->r_request_started); @@ -1260,7 +1249,7 @@ retry_lookup: if (d_really_is_negative(dn)) { ceph_dir_clear_ordered(dir); ihold(in); - dn = splice_dentry(dn, in, &have_lease); + dn = splice_dentry(dn, in); if (IS_ERR(dn)) { err = PTR_ERR(dn); goto done; @@ -1290,7 +1279,7 @@ retry_lookup: dout(" linking snapped dir %p to dn %p\n", in, dn); ceph_dir_clear_ordered(dir); ihold(in); - dn = splice_dentry(dn, in, NULL); + dn = splice_dentry(dn, in); if (IS_ERR(dn)) { err = PTR_ERR(dn); goto done; @@ -1501,7 +1490,7 @@ retry_lookup: } if (d_really_is_negative(dn)) { - struct dentry *realdn = splice_dentry(dn, in, NULL); + struct dentry *realdn = splice_dentry(dn, in); if (IS_ERR(realdn)) { err = PTR_ERR(realdn); d_drop(dn); diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index c48ca13673e3..09b1db2cac31 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -642,9 +642,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) while (*s && *s != sep) s++; - inode_lock(dir); - child = lookup_one_len(p, dentry, s - p); - inode_unlock(dir); + child = lookup_one_len_unlocked(p, dentry, s - p); dput(dentry); dentry = child; } while (!IS_ERR(dentry)); diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index f419519ec41f..214ec14149d9 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -432,14 +432,9 @@ static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * den (sd->s_type & CONFIGFS_ITEM_BIN_ATTR) ? configfs_init_bin_file : configfs_init_file); - if (error) { + if (error) configfs_put(sd); - return error; - } - - d_rehash(dentry); - - return 0; + return error; } static struct dentry * configfs_lookup(struct inode *dir, diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c index cee087d8f7e0..45811ea3fd87 100644 --- a/fs/configfs/inode.c +++ b/fs/configfs/inode.c @@ -199,9 +199,17 @@ int configfs_create(struct dentry * dentry, umode_t mode, void (*init)(struct in configfs_set_inode_lock_class(sd, inode); init(inode); - d_instantiate(dentry, inode); - if (S_ISDIR(mode) || S_ISLNK(mode)) + if (S_ISDIR(mode) || S_ISLNK(mode)) { + /* + * ->symlink(), ->mkdir(), configfs_register_subsystem() or + * create_default_group() - already hashed. + */ + d_instantiate(dentry, inode); dget(dentry); /* pin link and directory dentries in core */ + } else { + /* ->lookup() */ + d_add(dentry, inode); + } return error; } diff --git a/fs/dcache.c b/fs/dcache.c index 2398f9f94337..32ceae3e6112 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1745,13 +1745,12 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode) unsigned add_flags = d_flags_for_inode(inode); spin_lock(&dentry->d_lock); - if (inode) - hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry); + hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry); raw_write_seqcount_begin(&dentry->d_seq); __d_set_inode_and_type(dentry, inode, add_flags); raw_write_seqcount_end(&dentry->d_seq); + __fsnotify_d_instantiate(dentry); spin_unlock(&dentry->d_lock); - fsnotify_d_instantiate(dentry, inode); } /** @@ -1772,91 +1771,16 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode) void d_instantiate(struct dentry *entry, struct inode * inode) { BUG_ON(!hlist_unhashed(&entry->d_u.d_alias)); - if (inode) + if (inode) { spin_lock(&inode->i_lock); - __d_instantiate(entry, inode); - if (inode) + __d_instantiate(entry, inode); spin_unlock(&inode->i_lock); + } security_d_instantiate(entry, inode); } EXPORT_SYMBOL(d_instantiate); /** - * d_instantiate_unique - instantiate a non-aliased dentry - * @entry: dentry to instantiate - * @inode: inode to attach to this dentry - * - * Fill in inode information in the entry. On success, it returns NULL. - * If an unhashed alias of "entry" already exists, then we return the - * aliased dentry instead and drop one reference to inode. - * - * Note that in order to avoid conflicts with rename() etc, the caller - * had better be holding the parent directory semaphore. - * - * This also assumes that the inode count has been incremented - * (or otherwise set) by the caller to indicate that it is now - * in use by the dcache. - */ -static struct dentry *__d_instantiate_unique(struct dentry *entry, - struct inode *inode) -{ - struct dentry *alias; - int len = entry->d_name.len; - const char *name = entry->d_name.name; - unsigned int hash = entry->d_name.hash; - - if (!inode) { - __d_instantiate(entry, NULL); - return NULL; - } - - hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) { - /* - * Don't need alias->d_lock here, because aliases with - * d_parent == entry->d_parent are not subject to name or - * parent changes, because the parent inode i_mutex is held. - */ - if (alias->d_name.hash != hash) - continue; - if (alias->d_parent != entry->d_parent) - continue; - if (alias->d_name.len != len) - continue; - if (dentry_cmp(alias, name, len)) - continue; - __dget(alias); - return alias; - } - - __d_instantiate(entry, inode); - return NULL; -} - -struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode) -{ - struct dentry *result; - - BUG_ON(!hlist_unhashed(&entry->d_u.d_alias)); - - if (inode) - spin_lock(&inode->i_lock); - result = __d_instantiate_unique(entry, inode); - if (inode) - spin_unlock(&inode->i_lock); - - if (!result) { - security_d_instantiate(entry, inode); - return NULL; - } - - BUG_ON(!d_unhashed(result)); - iput(inode); - return result; -} - -EXPORT_SYMBOL(d_instantiate_unique); - -/** * d_instantiate_no_diralias - instantiate a non-aliased dentry * @entry: dentry to complete * @inode: inode to attach to this dentry @@ -2436,6 +2360,86 @@ void d_rehash(struct dentry * entry) } EXPORT_SYMBOL(d_rehash); + +/* inode->i_lock held if inode is non-NULL */ + +static inline void __d_add(struct dentry *dentry, struct inode *inode) +{ + if (inode) { + __d_instantiate(dentry, inode); + spin_unlock(&inode->i_lock); + } + security_d_instantiate(dentry, inode); + d_rehash(dentry); +} + +/** + * d_add - add dentry to hash queues + * @entry: dentry to add + * @inode: The inode to attach to this dentry + * + * This adds the entry to the hash queues and initializes @inode. + * The entry was actually filled in earlier during d_alloc(). + */ + +void d_add(struct dentry *entry, struct inode *inode) +{ + if (inode) + spin_lock(&inode->i_lock); + __d_add(entry, inode); +} +EXPORT_SYMBOL(d_add); + +/** + * d_exact_alias - find and hash an exact unhashed alias + * @entry: dentry to add + * @inode: The inode to go with this dentry + * + * If an unhashed dentry with the same name/parent and desired + * inode already exists, hash and return it. Otherwise, return + * NULL. + * + * Parent directory should be locked. + */ +struct dentry *d_exact_alias(struct dentry *entry, struct inode *inode) +{ + struct dentry *alias; + int len = entry->d_name.len; + const char *name = entry->d_name.name; + unsigned int hash = entry->d_name.hash; + + spin_lock(&inode->i_lock); + hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) { + /* + * Don't need alias->d_lock here, because aliases with + * d_parent == entry->d_parent are not subject to name or + * parent changes, because the parent inode i_mutex is held. + */ + if (alias->d_name.hash != hash) + continue; + if (alias->d_parent != entry->d_parent) + continue; + if (alias->d_name.len != len) + continue; + if (dentry_cmp(alias, name, len)) + continue; + spin_lock(&alias->d_lock); + if (!d_unhashed(alias)) { + spin_unlock(&alias->d_lock); + alias = NULL; + } else { + __dget_dlock(alias); + _d_rehash(alias); + spin_unlock(&alias->d_lock); + } + spin_unlock(&inode->i_lock); + return alias; + } + spin_unlock(&inode->i_lock); + return NULL; +} +EXPORT_SYMBOL(d_exact_alias); + /** * dentry_update_name_case - update case insensitive dentry with a new name * @dentry: dentry to be updated @@ -2772,10 +2776,9 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) BUG_ON(!d_unhashed(dentry)); - if (!inode) { - __d_instantiate(dentry, NULL); + if (!inode) goto out; - } + spin_lock(&inode->i_lock); if (S_ISDIR(inode->i_mode)) { struct dentry *new = __d_find_any_alias(inode); @@ -2809,12 +2812,8 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) return new; } } - /* already taking inode->i_lock, so d_add() by hand */ - __d_instantiate(dentry, inode); - spin_unlock(&inode->i_lock); out: - security_d_instantiate(dentry, inode); - d_rehash(dentry); + __d_add(dentry, inode); return NULL; } EXPORT_SYMBOL(d_splice_alias); diff --git a/fs/direct-io.c b/fs/direct-io.c index 1b2f7ffc8b84..85463171053b 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -445,7 +445,8 @@ static struct bio *dio_await_one(struct dio *dio) __set_current_state(TASK_UNINTERRUPTIBLE); dio->waiter = current; spin_unlock_irqrestore(&dio->bio_lock, flags); - if (!blk_poll(bdev_get_queue(dio->bio_bdev), dio->bio_cookie)) + if (!(dio->iocb->ki_flags & IOCB_HIPRI) || + !blk_poll(bdev_get_queue(dio->bio_bdev), dio->bio_cookie)) io_schedule(); /* wake up sets us TASK_RUNNING */ spin_lock_irqsave(&dio->bio_lock, flags); diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 80d6901493cf..87dbdd4881ab 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -1499,16 +1499,14 @@ out: */ static int ecryptfs_encrypt_filename(struct ecryptfs_filename *filename, - struct ecryptfs_crypt_stat *crypt_stat, struct ecryptfs_mount_crypt_stat *mount_crypt_stat) { int rc = 0; filename->encrypted_filename = NULL; filename->encrypted_filename_size = 0; - if ((crypt_stat && (crypt_stat->flags & ECRYPTFS_ENCFN_USE_MOUNT_FNEK)) - || (mount_crypt_stat && (mount_crypt_stat->flags - & ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK))) { + if (mount_crypt_stat && (mount_crypt_stat->flags + & ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK)) { size_t packet_size; size_t remaining_bytes; @@ -1944,7 +1942,6 @@ out: int ecryptfs_encrypt_and_encode_filename( char **encoded_name, size_t *encoded_name_size, - struct ecryptfs_crypt_stat *crypt_stat, struct ecryptfs_mount_crypt_stat *mount_crypt_stat, const char *name, size_t name_size) { @@ -1953,9 +1950,8 @@ int ecryptfs_encrypt_and_encode_filename( (*encoded_name) = NULL; (*encoded_name_size) = 0; - if ((crypt_stat && (crypt_stat->flags & ECRYPTFS_ENCRYPT_FILENAMES)) - || (mount_crypt_stat && (mount_crypt_stat->flags - & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES))) { + if (mount_crypt_stat && (mount_crypt_stat->flags + & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)) { struct ecryptfs_filename *filename; filename = kzalloc(sizeof(*filename), GFP_KERNEL); @@ -1968,8 +1964,7 @@ int ecryptfs_encrypt_and_encode_filename( } filename->filename = (char *)name; filename->filename_size = name_size; - rc = ecryptfs_encrypt_filename(filename, crypt_stat, - mount_crypt_stat); + rc = ecryptfs_encrypt_filename(filename, mount_crypt_stat); if (rc) { printk(KERN_ERR "%s: Error attempting to encrypt " "filename; rc = [%d]\n", __func__, rc); @@ -1980,11 +1975,9 @@ int ecryptfs_encrypt_and_encode_filename( NULL, &encoded_name_no_prefix_size, filename->encrypted_filename, filename->encrypted_filename_size); - if ((crypt_stat && (crypt_stat->flags - & ECRYPTFS_ENCFN_USE_MOUNT_FNEK)) - || (mount_crypt_stat + if (mount_crypt_stat && (mount_crypt_stat->flags - & ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK))) + & ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK)) (*encoded_name_size) = (ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE + encoded_name_no_prefix_size); @@ -2002,11 +1995,9 @@ int ecryptfs_encrypt_and_encode_filename( kfree(filename); goto out; } - if ((crypt_stat && (crypt_stat->flags - & ECRYPTFS_ENCFN_USE_MOUNT_FNEK)) - || (mount_crypt_stat + if (mount_crypt_stat && (mount_crypt_stat->flags - & ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK))) { + & ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK)) { memcpy((*encoded_name), ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX, ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE); diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 7b39260c7bba..67e16128c572 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -569,7 +569,6 @@ int ecryptfs_fill_zeros(struct file *file, loff_t new_length); int ecryptfs_encrypt_and_encode_filename( char **encoded_name, size_t *encoded_name_size, - struct ecryptfs_crypt_stat *crypt_stat, struct ecryptfs_mount_crypt_stat *mount_crypt_stat, const char *name, size_t name_size); struct dentry *ecryptfs_lower_dentry(struct dentry *this_dentry); diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 4e685ac1024d..26651636cd1d 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -397,11 +397,9 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, int rc = 0; lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent); - inode_lock(d_inode(lower_dir_dentry)); - lower_dentry = lookup_one_len(ecryptfs_dentry->d_name.name, + lower_dentry = lookup_one_len_unlocked(ecryptfs_dentry->d_name.name, lower_dir_dentry, ecryptfs_dentry->d_name.len); - inode_unlock(d_inode(lower_dir_dentry)); if (IS_ERR(lower_dentry)) { rc = PTR_ERR(lower_dentry); ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " @@ -419,18 +417,16 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, dput(lower_dentry); rc = ecryptfs_encrypt_and_encode_filename( &encrypted_and_encoded_name, &encrypted_and_encoded_name_size, - NULL, mount_crypt_stat, ecryptfs_dentry->d_name.name, + mount_crypt_stat, ecryptfs_dentry->d_name.name, ecryptfs_dentry->d_name.len); if (rc) { printk(KERN_ERR "%s: Error attempting to encrypt and encode " "filename; rc = [%d]\n", __func__, rc); goto out; } - inode_lock(d_inode(lower_dir_dentry)); - lower_dentry = lookup_one_len(encrypted_and_encoded_name, + lower_dentry = lookup_one_len_unlocked(encrypted_and_encoded_name, lower_dir_dentry, encrypted_and_encoded_name_size); - inode_unlock(d_inode(lower_dir_dentry)); if (IS_ERR(lower_dentry)) { rc = PTR_ERR(lower_dentry); ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned " @@ -502,7 +498,6 @@ static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry, dir->i_sb)->mount_crypt_stat; rc = ecryptfs_encrypt_and_encode_filename(&encoded_symname, &encoded_symlen, - NULL, mount_crypt_stat, symname, strlen(symname)); if (rc) diff --git a/fs/namei.c b/fs/namei.c index 9c590e0f66e9..794f81dce766 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1220,8 +1220,8 @@ static int follow_managed(struct path *path, struct nameidata *nd) if (need_mntput && path->mnt == mnt) mntput(path->mnt); - if (ret == -EISDIR) - ret = 0; + if (ret == -EISDIR || !ret) + ret = 1; if (need_mntput) nd->flags |= LOOKUP_JUMPED; if (unlikely(ret < 0)) @@ -1444,40 +1444,26 @@ static int follow_dotdot(struct nameidata *nd) * This looks up the name in dcache, possibly revalidates the old dentry and * allocates a new one if not found or not valid. In the need_lookup argument * returns whether i_op->lookup is necessary. - * - * dir->d_inode->i_mutex must be held */ -static struct dentry *lookup_dcache(struct qstr *name, struct dentry *dir, - unsigned int flags, bool *need_lookup) +static struct dentry *lookup_dcache(const struct qstr *name, + struct dentry *dir, + unsigned int flags) { struct dentry *dentry; int error; - *need_lookup = false; dentry = d_lookup(dir, name); if (dentry) { if (dentry->d_flags & DCACHE_OP_REVALIDATE) { error = d_revalidate(dentry, flags); if (unlikely(error <= 0)) { - if (error < 0) { - dput(dentry); - return ERR_PTR(error); - } else { + if (!error) d_invalidate(dentry); - dput(dentry); - dentry = NULL; - } + dput(dentry); + return ERR_PTR(error); } } } - - if (!dentry) { - dentry = d_alloc(dir, name); - if (unlikely(!dentry)) - return ERR_PTR(-ENOMEM); - - *need_lookup = true; - } return dentry; } @@ -1506,45 +1492,44 @@ static struct dentry *lookup_real(struct inode *dir, struct dentry *dentry, return dentry; } -static struct dentry *__lookup_hash(struct qstr *name, +static struct dentry *__lookup_hash(const struct qstr *name, struct dentry *base, unsigned int flags) { - bool need_lookup; - struct dentry *dentry; + struct dentry *dentry = lookup_dcache(name, base, flags); - dentry = lookup_dcache(name, base, flags, &need_lookup); - if (!need_lookup) + if (dentry) return dentry; + dentry = d_alloc(base, name); + if (unlikely(!dentry)) + return ERR_PTR(-ENOMEM); + return lookup_real(base->d_inode, dentry, flags); } -/* - * It's more convoluted than I'd like it to be, but... it's still fairly - * small and for now I'd prefer to have fast path as straight as possible. - * It _is_ time-critical. - */ static int lookup_fast(struct nameidata *nd, struct path *path, struct inode **inode, unsigned *seqp) { struct vfsmount *mnt = nd->path.mnt; struct dentry *dentry, *parent = nd->path.dentry; - int need_reval = 1; int status = 1; int err; /* * Rename seqlock is not required here because in the off chance - * of a false negative due to a concurrent rename, we're going to - * do the non-racy lookup, below. + * of a false negative due to a concurrent rename, the caller is + * going to fall back to non-racy lookup. */ if (nd->flags & LOOKUP_RCU) { unsigned seq; bool negative; dentry = __d_lookup_rcu(parent, &nd |
