projects/linux·commit 5ed487bc

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6

5ed487bc · Linus Torvalds <[email protected]> · 2008-10-23 10:22:40 -07:00

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (46 commits)
  [PATCH] fs: add a sanity check in d_free
  [PATCH] i_version: remount support
  [patch] vfs: make security_inode_setattr() calling consistent
  [patch 1/3] FS_MBCACHE: don't needlessly make it built-in
  [PATCH] move executable checking into ->permission()
  [PATCH] fs/dcache.c: update comment of d_validate()
  [RFC PATCH] touch_mnt_namespace when the mount flags change
  [PATCH] reiserfs: add missing llseek method
  [PATCH] fix ->llseek for more directories
  [PATCH vfs-2.6 6/6] vfs: add LOOKUP_RENAME_TARGET intent
  [PATCH vfs-2.6 5/6] vfs: remove LOOKUP_PARENT from non LOOKUP_PARENT lookup
  [PATCH vfs-2.6 4/6] vfs: remove unnecessary fsnotify_d_instantiate()
  [PATCH vfs-2.6 3/6] vfs: add __d_instantiate() helper
  [PATCH vfs-2.6 2/6] vfs: add d_ancestor()
  [PATCH vfs-2.6 1/6] vfs: replace parent == dentry->d_parent by IS_ROOT()
  [PATCH] get rid of on-stack dentry in udf
  [PATCH 2/2] anondev: switch to IDA
  [PATCH 1/2] anondev: init IDR statically
  [JFFS2] Use d_splice_alias() not d_add() in jffs2_lookup()
  [PATCH] Optimise NFS readdir hack slightly.
  ...
Commit
5ed487bc2c44ca4e9668ef9cb54c830e2a9fac47
Parents
5b346539 · fd217f4d

Merge commit. Changes below are compared with the first parent: 5b346539.

Changes

76 files changed · +883 −1133

FileStatusAddDelContent
arch/alpha/kernel/osf_sys.cmodified+2−5View file
arch/parisc/hpux/fs.cmodified+2−3View file
arch/powerpc/platforms/cell/spufs/syscalls.cmodified+2−2View file
drivers/md/dm-table.cmodified+6−15View file
fs/Kconfigmodified+4−3View file
fs/afs/dir.cmodified+1−0View file
fs/attr.cmodified+5−5View file
fs/bfs/dir.cmodified+1−0View file
fs/block_dev.cmodified+7−7View file
fs/char_dev.cmodified+14−7View file
fs/cifs/cifsfs.cmodified+7−3View file
fs/coda/dir.cmodified+3−0View file
fs/coda/pioctl.cmodified+1−1View file
fs/compat.cmodified+8−14View file
fs/configfs/symlink.cmodified+8−8View file
fs/dcache.cmodified+94−90View file
fs/dquot.cmodified+5−5View file
fs/ecryptfs/main.cmodified+9−14View file
fs/efs/namei.cmodified+4−25View file
fs/exportfs/expfs.cmodified+8−12View file
fs/ext2/dir.cmodified+7−7View file
fs/ext2/ext2.hmodified+2−2View file
fs/ext2/namei.cmodified+7−23View file
fs/ext3/namei.cmodified+34−50View file
fs/ext3/super.cmodified+11−11View file
fs/ext4/namei.cmodified+1−10View file
fs/ext4/super.cmodified+12−12View file
fs/fat/dir.cmodified+1−0View file
fs/fat/inode.cmodified+18−34View file
fs/fuse/inode.cmodified+8−15View file
fs/gfs2/ops_export.cmodified+9−24View file
fs/gfs2/ops_inode.cmodified+1−1View file
fs/hfs/inode.cmodified+0−8View file
fs/hfsplus/inode.cmodified+0−13View file
fs/hpfs/file.cmodified+1−1View file
fs/hpfs/hpfs_fn.hmodified+1−1View file
fs/hpfs/inode.cmodified+19−10View file
fs/hpfs/namei.cmodified+1−1View file
fs/isofs/export.cmodified+5−28View file
fs/jffs2/dir.cmodified+3−4View file
fs/jffs2/super.cmodified+48−0View file
fs/jfs/namei.cmodified+2−14View file
fs/libfs.cmodified+2−24View file
fs/namei.cmodified+68−78View file
fs/namespace.cmodified+65−68View file
fs/nfs/dir.cmodified+5−4View file
fs/nfs/getroot.cmodified+6−8View file
fs/nfsd/export.cmodified+58−67View file
fs/nfsd/nfs4recover.cmodified+25−25View file
fs/nfsd/nfs4state.cmodified+4−4View file
fs/nfsd/nfsctl.cmodified+4−4View file
fs/nfsd/vfs.cmodified+110−16View file
fs/ntfs/namei.cmodified+2−20View file
fs/ocfs2/export.cmodified+6−24View file
fs/omfs/dir.cmodified+1−0View file
fs/openpromfs/inode.cmodified+1−0View file
fs/proc/proc_sysctl.cmodified+9−2View file
fs/read_write.cmodified+40−18View file
fs/readdir.cmodified+8−14View file
fs/reiserfs/file.cmodified+1−0View file
fs/reiserfs/inode.cmodified+2−11View file
fs/reiserfs/namei.cmodified+1−10View file
fs/reiserfs/super.cmodified+9−9View file
fs/super.cmodified+5−10View file
fs/sysfs/dir.cmodified+1−0View file
fs/udf/namei.cmodified+13−30View file
fs/ufs/dir.cmodified+1−0View file
fs/xfs/linux-2.6/xfs_export.cmodified+3−29View file
fs/xfs/linux-2.6/xfs_file.cmodified+0−128View file
fs/xfs/linux-2.6/xfs_ioctl.cmodified+3−4View file
include/linux/dcache.hmodified+2−1View file
include/linux/fs.hmodified+6−2View file
include/linux/namei.hmodified+6−2View file
init/main.cmodified+0−1View file
kernel/audit_tree.cmodified+24−24View file
net/unix/af_unix.cmodified+10−8View file

Only the first 600 diff lines are shown. Download the complete patch.

arch/alpha/kernel/osf_sys.c

View file
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 8509dad..f25f6c4 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -165,14 +165,11 @@ osf_getdirentries(unsigned int fd, struct osf_dirent __user *dirent,
buf.error = 0;
error = vfs_readdir(file, osf_filldir, &buf);
- if (error < 0)
- goto out_putf;
-
- error = buf.error;
+ if (error >= 0)
+ error = buf.error;
if (count != buf.count)
error = count - buf.count;
- out_putf:
fput(file);
out:
return error;

arch/parisc/hpux/fs.c

View file
diff --git a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c
index 12c04c5..bd9a4db 100644
--- a/arch/parisc/hpux/fs.c
+++ b/arch/parisc/hpux/fs.c
@@ -127,9 +127,8 @@ int hpux_getdents(unsigned int fd, struct hpux_dirent __user *dirent, unsigned i
buf.error = 0;
error = vfs_readdir(file, filldir, &buf);
- if (error < 0)
- goto out_putf;
- error = buf.error;
+ if (error >= 0)
+ error = buf.error;
lastdirent = buf.previous;
if (lastdirent) {
if (put_user(file->f_pos, &lastdirent->d_off))

arch/powerpc/platforms/cell/spufs/syscalls.c

View file
diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c
index 49c8776..c23617c 100644
--- a/arch/powerpc/platforms/cell/spufs/syscalls.c
+++ b/arch/powerpc/platforms/cell/spufs/syscalls.c
@@ -69,9 +69,9 @@ static long do_spu_create(const char __user *pathname, unsigned int flags,
if (!IS_ERR(tmp)) {
struct nameidata nd;
- ret = path_lookup(tmp, LOOKUP_PARENT|
- LOOKUP_OPEN|LOOKUP_CREATE, &nd);
+ ret = path_lookup(tmp, LOOKUP_PARENT, &nd);
if (!ret) {
+ nd.flags |= LOOKUP_OPEN | LOOKUP_CREATE;
ret = spufs_create(&nd, flags, mode, neighbor);
path_put(&nd.path);
}

drivers/md/dm-table.c

View file
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index a740a69..1407eb9 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -313,19 +313,6 @@ static inline int check_space(struct dm_table *t)
}
/*
- * Convert a device path to a dev_t.
- */
-static int lookup_device(const char *path, dev_t *dev)
-{
- struct block_device *bdev = lookup_bdev(path);
- if (IS_ERR(bdev))
- return PTR_ERR(bdev);
- *dev = bdev->bd_dev;
- bdput(bdev);
- return 0;
-}
-
-/*
* See if we've already got a device in the list.
*/
static struct dm_dev_internal *find_device(struct list_head *l, dev_t dev)
@@ -437,8 +424,12 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti,
return -EOVERFLOW;
} else {
/* convert the path to a device */
- if ((r = lookup_device(path, &dev)))
- return r;
+ struct block_device *bdev = lookup_bdev(path);
+
+ if (IS_ERR(bdev))
+ return PTR_ERR(bdev);
+ dev = bdev->bd_dev;
+ bdput(bdev);
}
dd = find_device(&t->devices, dev);

fs/Kconfig

View file
diff --git a/fs/Kconfig b/fs/Kconfig
index e46297f..522469a 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -22,9 +22,10 @@ source "fs/jbd2/Kconfig"
config FS_MBCACHE
# Meta block cache for Extended Attributes (ext2/ext3/ext4)
tristate
- depends on EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4_FS_XATTR
- default y if EXT2_FS=y || EXT3_FS=y || EXT4_FS=y
- default m if EXT2_FS=m || EXT3_FS=m || EXT4_FS=m
+ default y if EXT2_FS=y && EXT2_FS_XATTR
+ default y if EXT3_FS=y && EXT3_FS_XATTR
+ default y if EXT4_FS=y && EXT4_FS_XATTR
+ default m if EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4_FS_XATTR
config REISERFS_FS
tristate "Reiserfs support"

fs/afs/dir.c

View file
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index dfda03d..99cf390 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -45,6 +45,7 @@ const struct file_operations afs_dir_file_operations = {
.release = afs_release,
.readdir = afs_readdir,
.lock = afs_lock,
+ .llseek = generic_file_llseek,
};
const struct inode_operations afs_dir_inode_operations = {

fs/attr.c

View file
diff --git a/fs/attr.c b/fs/attr.c
index 26c71ba..7a83819 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -159,17 +159,17 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
if (!(attr->ia_valid & ~(ATTR_KILL_SUID | ATTR_KILL_SGID)))
return 0;
+ error = security_inode_setattr(dentry, attr);
+ if (error)
+ return error;
+
if (ia_valid & ATTR_SIZE)
down_write(&dentry->d_inode->i_alloc_sem);
if (inode->i_op && inode->i_op->setattr) {
- error = security_inode_setattr(dentry, attr);
- if (!error)
- error = inode->i_op->setattr(dentry, attr);
+ error = inode->i_op->setattr(dentry, attr);
} else {
error = inode_change_ok(inode, attr);
- if (!error)
- error = security_inode_setattr(dentry, attr);
if (!error) {
if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
(ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid))

fs/bfs/dir.c

View file
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index ed8feb0..daae463 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -80,6 +80,7 @@ const struct file_operations bfs_dir_operations = {
.read = generic_read_dir,
.readdir = bfs_readdir,
.fsync = file_fsync,
+ .llseek = generic_file_llseek,
};
extern void dump_imap(const char *, struct super_block *);

fs/block_dev.c

View file
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 218408e..d06fe3c 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1268,33 +1268,33 @@ EXPORT_SYMBOL(ioctl_by_bdev);
* namespace if possible and return it. Return ERR_PTR(error)
* otherwise.
*/
-struct block_device *lookup_bdev(const char *path)
+struct block_device *lookup_bdev(const char *pathname)
{
struct block_device *bdev;
struct inode *inode;
- struct nameidata nd;
+ struct path path;
int error;
- if (!path || !*path)
+ if (!pathname || !*pathname)
return ERR_PTR(-EINVAL);
- error = path_lookup(path, LOOKUP_FOLLOW, &nd);
+ error = kern_path(pathname, LOOKUP_FOLLOW, &path);
if (error)
return ERR_PTR(error);
- inode = nd.path.dentry->d_inode;
+ inode = path.dentry->d_inode;
error = -ENOTBLK;
if (!S_ISBLK(inode->i_mode))
goto fail;
error = -EACCES;
- if (nd.path.mnt->mnt_flags & MNT_NODEV)
+ if (path.mnt->mnt_flags & MNT_NODEV)
goto fail;
error = -ENOMEM;
bdev = bd_acquire(inode);
if (!bdev)
goto fail;
out:
- path_put(&nd.path);
+ path_put(&path);
return bdev;
fail:
bdev = ERR_PTR(error);

fs/char_dev.c

View file
diff --git a/fs/char_dev.c b/fs/char_dev.c
index 262fa10..700697a 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -386,15 +386,22 @@ static int chrdev_open(struct inode *inode, struct file *filp)
cdev_put(new);
if (ret)
return ret;
+
+ ret = -ENXIO;
filp->f_op = fops_get(p->ops);
- if (!filp->f_op) {
- cdev_put(p);
- return -ENXIO;
- }
- if (filp->f_op->open)
+ if (!filp->f_op)
+ goto out_cdev_put;
+
+ if (filp->f_op->open) {
ret = filp->f_op->open(inode,filp);
- if (ret)
- cdev_put(p);
+ if (ret)
+ goto out_cdev_put;
+ }
+
+ return 0;
+
+ out_cdev_put:
+ cdev_put(p);
return ret;
}

fs/cifs/cifsfs.c

View file
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 25ecbd5..84cc011 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -275,9 +275,12 @@ static int cifs_permission(struct inode *inode, int mask)
cifs_sb = CIFS_SB(inode->i_sb);
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
- return 0;
- else /* file mode might have been restricted at mount time
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
+ if ((mask & MAY_EXEC) && !execute_ok(inode))
+ return -EACCES;
+ else
+ return 0;
+ } else /* file mode might have been restricted at mount time
on the client (above and beyond ACL on servers) for
servers which do not support setting and viewing mode bits,
so allowing client to check permissions is useful */
@@ -765,6 +768,7 @@ const struct file_operations cifs_dir_ops = {
.dir_notify = cifs_dir_notify,
#endif /* CONFIG_CIFS_EXPERIMENTAL */
.unlocked_ioctl = cifs_ioctl,
+ .llseek = generic_file_llseek,
};
static void

fs/coda/dir.c

View file
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index c591622..75b1fa9 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -146,6 +146,9 @@ int coda_permission(struct inode *inode, int mask)
if (!mask)
return 0;
+ if ((mask & MAY_EXEC) && !execute_ok(inode))
+ return -EACCES;
+
lock_kernel();
if (coda_cache_check(inode, mask))

fs/coda/pioctl.c

View file
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c
index c513654..773f2ce 100644
--- a/fs/coda/pioctl.c
+++ b/fs/coda/pioctl.c
@@ -43,7 +43,7 @@ const struct file_operations coda_ioctl_operations = {
/* the coda pioctl inode ops */
static int coda_ioctl_permission(struct inode *inode, int mask)
{
- return 0;
+ return (mask & MAY_EXEC) ? -EACCES : 0;
}
static int coda_pioctl(struct inode * inode, struct file * filp,

fs/compat.c

View file
diff --git a/fs/compat.c b/fs/compat.c
index 5f9ec44..cb36245 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -869,7 +869,7 @@ asmlinkage long compat_sys_old_readdir(unsigned int fd,
buf.dirent = dirent;
error = vfs_readdir(file, compat_fillonedir, &buf);
- if (error >= 0)
+ if (buf.result)
error = buf.result;
fput(file);
@@ -956,9 +956,8 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
buf.error = 0;
error = vfs_readdir(file, compat_filldir, &buf);
- if (error < 0)
- goto out_putf;
- error = buf.error;
+ if (error >= 0)
+ error = buf.error;
lastdirent = buf.previous;
if (lastdirent) {
if (put_user(file->f_pos, &lastdirent->d_off))
@@ -966,8 +965,6 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
else
error = count - buf.count;
}
-
-out_putf:
fput(file);
out:
return error;
@@ -1047,19 +1044,16 @@ asmlinkage long compat_sys_getdents64(unsigned int fd,
buf.error = 0;
error = vfs_readdir(file, compat_filldir64, &buf);
- if (error < 0)
- goto out_putf;
- error = buf.error;
+ if (error >= 0)
+ error = buf.error;
lastdirent = buf.previous;
if (lastdirent) {
typeof(lastdirent->d_off) d_off = file->f_pos;
- error = -EFAULT;
if (__put_user_unaligned(d_off, &lastdirent->d_off))
- goto out_putf;
- error = count - buf.count;
+ error = -EFAULT;
+ else
+ error = count - buf.count;
}
-
-out_putf:
fput(file);
out:
return error;

fs/configfs/symlink.c

View file
diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c
index bf74973..932a92b 100644
--- a/fs/configfs/symlink.c
+++ b/fs/configfs/symlink.c
@@ -108,18 +108,18 @@ out:
}
-static int get_target(const char *symname, struct nameidata *nd,
+static int get_target(const char *symname, struct path *path,
struct config_item **target)
{
int ret;
- ret = path_lookup(symname, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, nd);
+ ret = kern_path(symname, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, path);
if (!ret) {
- if (nd->path.dentry->d_sb == configfs_sb) {
- *target = configfs_get_config_item(nd->path.dentry);
+ if (path->dentry->d_sb == configfs_sb) {
+ *target = configfs_get_config_item(path->dentry);
if (!*target) {
ret = -ENOENT;
- path_put(&nd->path);
+ path_put(path);
}
} else
ret = -EPERM;
@@ -132,7 +132,7 @@ static int get_target(const char *symname, struct nameidata *nd,
int configfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
{
int ret;
- struct nameidata nd;
+ struct path path;
struct configfs_dirent *sd;
struct config_item *parent_item;
struct config_item *target_item;
@@ -159,7 +159,7 @@ int configfs_symlink(struct inode *dir, struct dentry *dentry, const char *symna
!type->ct_item_ops->allow_link)
goto out_put;
- ret = get_target(symname, &nd, &target_item);
+ ret = get_target(symname, &path, &target_item);
if (ret)
goto out_put;
@@ -174,7 +174,7 @@ int configfs_symlink(struct inode *dir, struct dentry *dentry, const char *symna
}
config_item_put(target_item);
- path_put(&nd.path);
+ path_put(&path);
out_put:
config_item_put(parent_item);

fs/dcache.c

View file
diff --git a/fs/dcache.c b/fs/dcache.c
index e7a1a99..a1d86c7 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -69,6 +69,7 @@ struct dentry_stat_t dentry_stat = {
static void __d_free(struct dentry *dentry)
{
+ WARN_ON(!list_empty(&dentry->d_alias));
if (dname_external(dentry))
kfree(dentry->d_name.name);
kmem_cache_free(dentry_cache, dentry);
@@ -174,9 +175,12 @@ static struct dentry *d_kill(struct dentry *dentry)
dentry_stat.nr_dentry--; /* For d_free, below */
/*drops the locks, at that point nobody can reach this dentry */
dentry_iput(dentry);
- parent = dentry->d_parent;
+ if (IS_ROOT(dentry))
+ parent = NULL;
+ else
+ parent = dentry->d_parent;
d_free(dentry);
- return dentry == parent ? NULL : parent;
+ return parent;
}
/*
@@ -666,11 +670,12 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
BUG();
}
- parent = dentry->d_parent;
- if (parent == dentry)
+ if (IS_ROOT(dentry))
parent = NULL;
- else
+ else {
+ parent = dentry->d_parent;
atomic_dec(&parent->d_count);
+ }
list_del(&dentry->d_u.d_child);
detached++;
@@ -977,6 +982,15 @@ struct dentry *d_alloc_name(struct dentry *parent, const char *name)
return d_alloc(parent, &q);
}
+/* the caller must hold dcache_lock */
+static void __d_instantiate(struct dentry *dentry, struct inode *inode)
+{
+ if (inode)
+ list_add(&dentry->d_alias, &inode->i_dentry);
+ dentry->d_inode = inode;
+ fsnotify_d_instantiate(dentry, inode);
+}
+
/**
* d_instantiate - fill in inode information for a dentry
* @entry: dentry to complete
@@ -996,10 +1010,7 @@ void d_instantiate(struct dentry *entry, struct inode * inode)
{
BUG_ON(!list_empty(&entry->d_alias));
spin_lock(&dcache_lock);
- if (inode)
- list_add(&entry->d_alias, &inode->i_dentry);
- entry->d_inode = inode;
- fsnotify_d_instantiate(entry, inode);
+ __d_instantiate(entry, inode);
spin_unlock(&dcache_lock);
security_d_instantiate(entry, inode);
}
@@ -1029,7 +1040,7 @@ static struct dentry *__d_instantiate_unique(struct dentry *entry,
unsigned int hash = entry->d_name.hash;
if (!inode) {
- entry->d_inode = NULL;
+ __d_instantiate(entry, NULL);
return NULL;
}
@@ -1048,9 +1059,7 @@ static struct dentry *__d_instantiate_unique(struct dentry *entry,
return alias;
}
- list_add(&entry->d_alias, &inode->i_dentry);
- entry->d_inode = inode;
- fsnotify_d_instantiate(entry, inode);
+ __d_instantiate(entry, inode);
return NULL;
}
@@ -1111,69 +1120,71 @@ static inline struct hlist_head *d_hash(struct dentry *parent,
}
/**
- * d_alloc_anon - allocate an anonymous dentry
+ * d_obtain_alias - find or allocate a dentry for a given inode
* @inode: inode to allocate the dentry for
*
- * This is similar to d_alloc_root. It is used by filesystems when
- * creating a dentry for a given inode, often in the process of
- * mapping a filehandle to a dentry. The returned dentry may be
- * anonymous, or may have a full name (if the inode was already
- * in the cache). The file system may need to make further
- * efforts to connect this dentry into the dcache properly.
+ * Obtain a dentry for an inode resulting from NFS filehandle conversion or
+ * similar open by handle operations. The returned dentry may be anonymous,
+ * or may have a full name (if the inode was already in the cache).
*
- * When called on a directory inode, we must ensure that
- * the inode only ever has one dentry. If a dentry is
- * found, that is returned instead of allocating a new one.
+ * When called on a directory inode, we must ensure that the inode only ever
+ * has one dentry. If a dentry is found, that is returned instead of
+ * allocating a new one.
*
* On successful return, the reference to the inode has been transferred
- * to the dentry. If %NULL is returned (indicating kmalloc failure),
- * the reference on the inode has not been released.
+ * to the dentry. In case of an error the reference on the inode is released.
+ * To make it easier to use in export operations a %NULL or IS_ERR inode may
+ * be passed in and will be the error will be propagate to the return value,
+ * with a %NULL @inode replaced by ERR_PTR(-ESTALE).
*/
-
-struct dentry * d_alloc_anon(struct inode *inode)
+struct dentry *d_obtain_alias(struct inode *inode)
{
static const struct qstr anonstring = { .name = "" };
struct dentry *tmp;
struct dentry *res;
- if ((res = d_find_alias(inode))) {
- iput(inode);
- return res;
- }
+ if (!inode)
+ return ERR_PTR(-ESTALE);
+ if (IS_ERR(inode))
+ return ERR_CAST(inode);
- tmp = d_alloc(NULL, &anonstring);
- if (!tmp)
- return NULL;
+ res = d_find_alias(inode);
+ if (res)
+ goto out_iput;
+ tmp = d_alloc(NULL, &anonstring);
+ if (!tmp) {
+ res = ERR_PTR(-ENOMEM);
+ goto out_iput;
+ }
tmp->d_parent = tmp; /* make sure dput doesn't croak */
-
+
spin_lock(&dcache_lock);
res = __d_find_alias(inode, 0);
- if (!res) {
- /* attach a disconnected dentry */
- res = tmp;
- tmp = NULL;
- spin_lock(&res->d_lock);
- res->d_sb = inode->i_sb;
- res->d_parent = res;
- res->d_inode = inode;
- res->d_flags |= DCACHE_DISCONNECTED;
- res->d_flags &= ~DCACHE_UNHASHED;
- list_add(&res->d_alias, &inode->i_dentry);
- hlist_add_head(&res->d_hash, &inode->i_sb->s_anon);
- spin_unlock(&res->d_lock);
-
- inode = NULL; /* don't drop reference */
+ if (res) {
+ spin_unlock(&dcache_lock);
+ dput(tmp);
+ goto out_iput;
}
+
+ /* attach a disconnected dentry */
+ spin_lock(&tmp->d_lock);
+ tmp->d_sb = inode->i_sb;
+ tmp->d_inode = inode;
+ tmp->d_flags |= DCACHE_DISCONNECTED;
+ tmp->d_flags &= ~DCACHE_UNHASHED;
+ list_add(&tmp->d_alias, &inode->i_dentry);
+ hlist_add_head(&tmp->d_hash, &inode->i_sb->s_anon);
+ spin_unlock(&tmp->d_lock);
+
spin_unlock(&dcache_lock);
+ return tmp;

This diff is incomplete. Download the complete patch.

fs/dquot.c

View file

This diff is incomplete. Download the complete patch.

fs/ecryptfs/main.c

View file

This diff is incomplete. Download the complete patch.

fs/efs/namei.c

View file

This diff is incomplete. Download the complete patch.

fs/exportfs/expfs.c

View file

This diff is incomplete. Download the complete patch.

fs/ext2/dir.c

View file

This diff is incomplete. Download the complete patch.

fs/ext2/ext2.h

View file

This diff is incomplete. Download the complete patch.

fs/ext2/namei.c

View file

This diff is incomplete. Download the complete patch.

fs/ext3/namei.c

View file

This diff is incomplete. Download the complete patch.

fs/ext3/super.c

View file

This diff is incomplete. Download the complete patch.

fs/ext4/namei.c

View file

This diff is incomplete. Download the complete patch.

fs/ext4/super.c

View file

This diff is incomplete. Download the complete patch.

fs/fat/dir.c

View file

This diff is incomplete. Download the complete patch.

fs/fat/inode.c

View file

This diff is incomplete. Download the complete patch.

fs/fuse/inode.c

View file

This diff is incomplete. Download the complete patch.

fs/gfs2/ops_export.c

View file

This diff is incomplete. Download the complete patch.

fs/gfs2/ops_inode.c

View file

This diff is incomplete. Download the complete patch.

fs/hfs/inode.c

View file

This diff is incomplete. Download the complete patch.

fs/hfsplus/inode.c

View file

This diff is incomplete. Download the complete patch.

fs/hpfs/file.c

View file

This diff is incomplete. Download the complete patch.

fs/hpfs/hpfs_fn.h

View file

This diff is incomplete. Download the complete patch.

fs/hpfs/inode.c

View file

This diff is incomplete. Download the complete patch.

fs/hpfs/namei.c

View file

This diff is incomplete. Download the complete patch.

fs/isofs/export.c

View file

This diff is incomplete. Download the complete patch.

fs/jffs2/dir.c

View file

This diff is incomplete. Download the complete patch.

fs/jffs2/super.c

View file

This diff is incomplete. Download the complete patch.

fs/jfs/namei.c

View file

This diff is incomplete. Download the complete patch.

fs/libfs.c

View file

This diff is incomplete. Download the complete patch.

fs/namei.c

View file

This diff is incomplete. Download the complete patch.

fs/namespace.c

View file

This diff is incomplete. Download the complete patch.

fs/nfs/dir.c

View file

This diff is incomplete. Download the complete patch.

fs/nfs/getroot.c

View file

This diff is incomplete. Download the complete patch.

fs/nfsd/export.c

View file

This diff is incomplete. Download the complete patch.

fs/nfsd/nfs4recover.c

View file

This diff is incomplete. Download the complete patch.

fs/nfsd/nfs4state.c

View file

This diff is incomplete. Download the complete patch.

fs/nfsd/nfsctl.c

View file

This diff is incomplete. Download the complete patch.

fs/nfsd/vfs.c

View file

This diff is incomplete. Download the complete patch.

fs/ntfs/namei.c

View file

This diff is incomplete. Download the complete patch.

fs/ocfs2/export.c

View file

This diff is incomplete. Download the complete patch.

fs/omfs/dir.c

View file

This diff is incomplete. Download the complete patch.

fs/openpromfs/inode.c

View file

This diff is incomplete. Download the complete patch.

fs/proc/proc_sysctl.c

View file

This diff is incomplete. Download the complete patch.

fs/read_write.c

View file

This diff is incomplete. Download the complete patch.

fs/readdir.c

View file

This diff is incomplete. Download the complete patch.

fs/reiserfs/file.c

View file

This diff is incomplete. Download the complete patch.

fs/reiserfs/inode.c

View file

This diff is incomplete. Download the complete patch.

fs/reiserfs/namei.c

View file

This diff is incomplete. Download the complete patch.

fs/reiserfs/super.c

View file

This diff is incomplete. Download the complete patch.

fs/super.c

View file

This diff is incomplete. Download the complete patch.

fs/sysfs/dir.c

View file

This diff is incomplete. Download the complete patch.

fs/udf/namei.c

View file

This diff is incomplete. Download the complete patch.

fs/ufs/dir.c

View file

This diff is incomplete. Download the complete patch.

fs/xfs/linux-2.6/xfs_export.c

View file

This diff is incomplete. Download the complete patch.

fs/xfs/linux-2.6/xfs_file.c

View file

This diff is incomplete. Download the complete patch.

fs/xfs/linux-2.6/xfs_ioctl.c

View file

This diff is incomplete. Download the complete patch.

include/linux/dcache.h

View file

This diff is incomplete. Download the complete patch.

include/linux/fs.h

View file

This diff is incomplete. Download the complete patch.

include/linux/namei.h

View file

This diff is incomplete. Download the complete patch.

init/main.c

View file

This diff is incomplete. Download the complete patch.

kernel/audit_tree.c

View file

This diff is incomplete. Download the complete patch.

net/unix/af_unix.c

View file

This diff is incomplete. Download the complete patch.