Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/viro/vfs-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (107 commits)
  vfs: use ERR_CAST for err-ptr tossing in lookup_instantiate_filp
  isofs: Remove global fs lock
  jffs2: fix IN_DELETE_SELF on overwriting rename() killing a directory
  fix IN_DELETE_SELF on overwriting rename() on ramfs et.al.
  mm/truncate.c: fix build for CONFIG_BLOCK not enabled
  fs:update the NOTE of the file_operations structure
  Remove dead code in dget_parent()
  AFS: Fix silly characters in a comment
  switch d_add_ci() to d_splice_alias() in "found negative" case as well
  simplify gfs2_lookup()
  jfs_lookup(): don't bother with . or ..
  get rid of useless dget_parent() in btrfs rename() and link()
  get rid of useless dget_parent() in fs/btrfs/ioctl.c
  fs: push i_mutex and filemap_write_and_wait down into ->fsync() handlers
  drivers: fix up various ->llseek() implementations
  fs: handle SEEK_HOLE/SEEK_DATA properly in all fs's that define their own llseek
  Ext4: handle SEEK_HOLE/SEEK_DATA generically
  Btrfs: implement our own ->llseek
  fs: add SEEK_HOLE and SEEK_DATA flags
  reiserfs: make reiserfs default to barrier=flush
  ...

Fix up trivial conflicts in fs/xfs/linux-2.6/xfs_super.c due to the new
shrinker callout for the inode cache, that clashed with the xfs code to
start the periodic workers later.
  • Loading branch information
torvalds committed Jul 23, 2011
2 parents 8e20487 + 5a9a436 commit bbd9d6f
Show file tree
Hide file tree
Showing 235 changed files with 2,517 additions and 1,948 deletions.
8 changes: 3 additions & 5 deletions Documentation/filesystems/Locking
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ ata *);
void (*put_link) (struct dentry *, struct nameidata *, void *);
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int, unsigned int);
int (*check_acl)(struct inode *, int, unsigned int);
int (*check_acl)(struct inode *, int);
int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
Expand Down Expand Up @@ -412,7 +412,7 @@ prototypes:
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, int datasync);
int (*fsync) (struct file *, loff_t start, loff_t end, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
Expand All @@ -438,9 +438,7 @@ prototypes:

locking rules:
All may block except for ->setlease.
No VFS locks held on entry except for ->fsync and ->setlease.

->fsync() has i_mutex on inode.
No VFS locks held on entry except for ->setlease.

->setlease has the file_list_lock held and must not sleep.

Expand Down
27 changes: 24 additions & 3 deletions Documentation/filesystems/porting
Original file line number Diff line number Diff line change
Expand Up @@ -398,12 +398,33 @@ Currently you can only have FALLOC_FL_PUNCH_HOLE with FALLOC_FL_KEEP_SIZE set,
so the i_size should not change when hole punching, even when puching the end of
a file off.

--
[mandatory]

--
[mandatory]
->get_sb() is gone. Switch to use of ->mount(). Typically it's just
a matter of switching from calling get_sb_... to mount_... and changing the
function type. If you were doing it manually, just switch from setting ->mnt_root
to some pointer to returning that pointer. On errors return ERR_PTR(...).

--
[mandatory]
->permission(), generic_permission() and ->check_acl() have lost flags
argument; instead of passing IPERM_FLAG_RCU we add MAY_NOT_BLOCK into mask.
generic_permission() has also lost the check_acl argument; if you want
non-NULL to be used for that inode, put it into ->i_op->check_acl.

--
[mandatory]
If you implement your own ->llseek() you must handle SEEK_HOLE and
SEEK_DATA. You can hanle this by returning -EINVAL, but it would be nicer to
support it in some way. The generic handler assumes that the entire file is
data and there is a virtual hole at the end of the file. So if the provided
offset is less than i_size and SEEK_DATA is specified, return the same offset.
If the above is true for the offset and you are given SEEK_HOLE, return the end
of the file. If the offset is i_size or greater return -ENXIO in either case.

[mandatory]
If you have your own ->fsync() you must make sure to call
filemap_write_and_wait_range() so that all dirty pages are synced out properly.
You must also keep in mind that ->fsync() is not called with i_mutex held
anymore, so if you require i_mutex locking you must make sure to take it and
release it yourself.
30 changes: 26 additions & 4 deletions Documentation/filesystems/vfs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ struct super_operations {

ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
int (*nr_cached_objects)(struct super_block *);
void (*free_cached_objects)(struct super_block *, int);
};

All methods are called without any locks being held, unless otherwise
Expand Down Expand Up @@ -301,6 +303,26 @@ or bottom half).

quota_write: called by the VFS to write to filesystem quota file.

nr_cached_objects: called by the sb cache shrinking function for the
filesystem to return the number of freeable cached objects it contains.
Optional.

free_cache_objects: called by the sb cache shrinking function for the
filesystem to scan the number of objects indicated to try to free them.
Optional, but any filesystem implementing this method needs to also
implement ->nr_cached_objects for it to be called correctly.

We can't do anything with any errors that the filesystem might
encountered, hence the void return type. This will never be called if
the VM is trying to reclaim under GFP_NOFS conditions, hence this
method does not need to handle that situation itself.

Implementations must include conditional reschedule calls inside any
scanning loop that is done. This allows the VFS to determine
appropriate scan batch sizes without having to worry about whether
implementations will cause holdoff problems due to large scan batch
sizes.

Whoever sets up the inode is responsible for filling in the "i_op" field. This
is a pointer to a "struct inode_operations" which describes the methods that
can be performed on individual inodes.
Expand Down Expand Up @@ -333,8 +355,8 @@ struct inode_operations {
void * (*follow_link) (struct dentry *, struct nameidata *);
void (*put_link) (struct dentry *, struct nameidata *, void *);
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int, unsigned int);
int (*check_acl)(struct inode *, int, unsigned int);
int (*permission) (struct inode *, int);
int (*check_acl)(struct inode *, int);
int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
Expand Down Expand Up @@ -423,7 +445,7 @@ otherwise noted.
permission: called by the VFS to check for access rights on a POSIX-like
filesystem.

May be called in rcu-walk mode (flags & IPERM_FLAG_RCU). If in rcu-walk
May be called in rcu-walk mode (mask & MAY_NOT_BLOCK). If in rcu-walk
mode, the filesystem must check the permission without blocking or
storing to the inode.

Expand Down Expand Up @@ -755,7 +777,7 @@ struct file_operations {
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, int datasync);
int (*fsync) (struct file *, loff_t, loff_t, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
Expand Down
7 changes: 2 additions & 5 deletions arch/arm/mach-tegra/clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ static const struct file_operations possible_parents_fops = {

static int clk_debugfs_register_one(struct clk *c)
{
struct dentry *d, *child, *child_tmp;
struct dentry *d;

d = debugfs_create_dir(c->name, clk_debugfs_root);
if (!d)
Expand Down Expand Up @@ -614,10 +614,7 @@ static int clk_debugfs_register_one(struct clk *c)
return 0;

err_out:
d = c->dent;
list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
debugfs_remove(child);
debugfs_remove(c->dent);
debugfs_remove_recursive(c->dent);
return -ENOMEM;
}

Expand Down
31 changes: 7 additions & 24 deletions arch/arm/mach-ux500/clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -635,16 +635,13 @@ static const struct file_operations set_rate_fops = {
static struct dentry *clk_debugfs_register_dir(struct clk *c,
struct dentry *p_dentry)
{
struct dentry *d, *clk_d, *child, *child_tmp;
char s[255];
char *p = s;
struct dentry *d, *clk_d;
const char *p = c->name;

if (c->name == NULL)
p += sprintf(p, "BUG");
else
p += sprintf(p, "%s", c->name);
if (!p)
p = "BUG";

clk_d = debugfs_create_dir(s, p_dentry);
clk_d = debugfs_create_dir(p, p_dentry);
if (!clk_d)
return NULL;

Expand All @@ -666,24 +663,10 @@ static struct dentry *clk_debugfs_register_dir(struct clk *c,
return clk_d;

err_out:
d = clk_d;
list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
debugfs_remove(child);
debugfs_remove(clk_d);
debugfs_remove_recursive(clk_d);
return NULL;
}

static void clk_debugfs_remove_dir(struct dentry *cdentry)
{
struct dentry *d, *child, *child_tmp;

d = cdentry;
list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
debugfs_remove(child);
debugfs_remove(cdentry);
return ;
}

static int clk_debugfs_register_one(struct clk *c)
{
struct clk *pa = c->parent_periph;
Expand All @@ -700,7 +683,7 @@ static int clk_debugfs_register_one(struct clk *c)
c->dent_bus = clk_debugfs_register_dir(c,
bpa->dent_bus ? bpa->dent_bus : bpa->dent);
if ((!c->dent_bus) && (c->dent)) {
clk_debugfs_remove_dir(c->dent);
debugfs_remove_recursive(c->dent);
c->dent = NULL;
return -ENOMEM;
}
Expand Down
12 changes: 3 additions & 9 deletions arch/arm/plat-omap/clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -480,13 +480,10 @@ static struct dentry *clk_debugfs_root;
static int clk_debugfs_register_one(struct clk *c)
{
int err;
struct dentry *d, *child, *child_tmp;
struct dentry *d;
struct clk *pa = c->parent;
char s[255];
char *p = s;

p += sprintf(p, "%s", c->name);
d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root);
d = debugfs_create_dir(c->name, pa ? pa->dent : clk_debugfs_root);
if (!d)
return -ENOMEM;
c->dent = d;
Expand All @@ -509,10 +506,7 @@ static int clk_debugfs_register_one(struct clk *c)
return 0;

err_out:
d = c->dent;
list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
debugfs_remove(child);
debugfs_remove(c->dent);
debugfs_remove_recursive(c->dent);
return err;
}

Expand Down
7 changes: 2 additions & 5 deletions arch/arm/plat-samsung/clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ static struct dentry *clk_debugfs_root;
static int clk_debugfs_register_one(struct clk *c)
{
int err;
struct dentry *d, *child, *child_tmp;
struct dentry *d;
struct clk *pa = c->parent;
char s[255];
char *p = s;
Expand Down Expand Up @@ -488,10 +488,7 @@ static int clk_debugfs_register_one(struct clk *c)
return 0;

err_out:
d = c->dent;
list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
debugfs_remove(child);
debugfs_remove(c->dent);
debugfs_remove_recursive(c->dent);
return err;
}

Expand Down
7 changes: 2 additions & 5 deletions arch/arm/plat-spear/clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -916,7 +916,7 @@ static struct dentry *clk_debugfs_root;
static int clk_debugfs_register_one(struct clk *c)
{
int err;
struct dentry *d, *child;
struct dentry *d;
struct clk *pa = c->pclk;
char s[255];
char *p = s;
Expand Down Expand Up @@ -951,10 +951,7 @@ static int clk_debugfs_register_one(struct clk *c)
return 0;

err_out:
d = c->dent;
list_for_each_entry(child, &d->d_subdirs, d_u.d_child)
debugfs_remove(child);
debugfs_remove(c->dent);
debugfs_remove_recursive(c->dent);
return err;
}

Expand Down
11 changes: 9 additions & 2 deletions arch/powerpc/platforms/cell/spufs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1850,9 +1850,16 @@ static int spufs_mfc_flush(struct file *file, fl_owner_t id)
return ret;
}

static int spufs_mfc_fsync(struct file *file, int datasync)
static int spufs_mfc_fsync(struct file *file, loff_t start, loff_t end, int datasync)
{
return spufs_mfc_flush(file, NULL);
struct inode *inode = file->f_path.dentry->d_inode;
int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
if (!err) {
mutex_lock(&inode->i_mutex);
err = spufs_mfc_flush(file, NULL);
mutex_unlock(&inode->i_mutex);
}
return err;
}

static int spufs_mfc_fasync(int fd, struct file *file, int on)
Expand Down
29 changes: 11 additions & 18 deletions arch/powerpc/platforms/cell/spufs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -611,49 +611,42 @@ static int spufs_create_gang(struct inode *inode,

static struct file_system_type spufs_type;

long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode,
struct file *filp)
long spufs_create(struct path *path, struct dentry *dentry,
unsigned int flags, mode_t mode, struct file *filp)
{
struct dentry *dentry;
int ret;

ret = -EINVAL;
/* check if we are on spufs */
if (nd->path.dentry->d_sb->s_type != &spufs_type)
if (path->dentry->d_sb->s_type != &spufs_type)
goto out;

/* don't accept undefined flags */
if (flags & (~SPU_CREATE_FLAG_ALL))
goto out;

/* only threads can be underneath a gang */
if (nd->path.dentry != nd->path.dentry->d_sb->s_root) {
if (path->dentry != path->dentry->d_sb->s_root) {
if ((flags & SPU_CREATE_GANG) ||
!SPUFS_I(nd->path.dentry->d_inode)->i_gang)
!SPUFS_I(path->dentry->d_inode)->i_gang)
goto out;
}

dentry = lookup_create(nd, 1);
ret = PTR_ERR(dentry);
if (IS_ERR(dentry))
goto out_dir;

mode &= ~current_umask();

if (flags & SPU_CREATE_GANG)
ret = spufs_create_gang(nd->path.dentry->d_inode,
dentry, nd->path.mnt, mode);
ret = spufs_create_gang(path->dentry->d_inode,
dentry, path->mnt, mode);
else
ret = spufs_create_context(nd->path.dentry->d_inode,
dentry, nd->path.mnt, flags, mode,
ret = spufs_create_context(path->dentry->d_inode,
dentry, path->mnt, flags, mode,
filp);
if (ret >= 0)
fsnotify_mkdir(nd->path.dentry->d_inode, dentry);
fsnotify_mkdir(path->dentry->d_inode, dentry);
return ret;

out_dir:
mutex_unlock(&nd->path.dentry->d_inode->i_mutex);
out:
mutex_unlock(&path->dentry->d_inode->i_mutex);
return ret;
}

Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/platforms/cell/spufs/spufs.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ extern const struct spufs_tree_descr spufs_dir_debug_contents[];
/* system call implementation */
extern struct spufs_calls spufs_calls;
long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *status);
long spufs_create(struct nameidata *nd, unsigned int flags,
long spufs_create(struct path *nd, struct dentry *dentry, unsigned int flags,
mode_t mode, struct file *filp);
/* ELF coredump callbacks for writing SPU ELF notes */
extern int spufs_coredump_extra_notes_size(void);
Expand Down
22 changes: 9 additions & 13 deletions arch/powerpc/platforms/cell/spufs/syscalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,21 +62,17 @@ static long do_spu_run(struct file *filp,
static long do_spu_create(const char __user *pathname, unsigned int flags,
mode_t mode, struct file *neighbor)
{
char *tmp;
struct path path;
struct dentry *dentry;
int ret;

tmp = getname(pathname);
ret = PTR_ERR(tmp);
if (!IS_ERR(tmp)) {
struct nameidata nd;

ret = kern_path_parent(tmp, &nd);
if (!ret) {
nd.flags |= LOOKUP_OPEN | LOOKUP_CREATE;
ret = spufs_create(&nd, flags, mode, neighbor);
path_put(&nd.path);
}
putname(tmp);
dentry = user_path_create(AT_FDCWD, pathname, &path, 1);
ret = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
ret = spufs_create(&path, dentry, flags, mode, neighbor);
mutex_unlock(&path.dentry->d_inode->i_mutex);
dput(dentry);
path_put(&path);
}

return ret;
Expand Down
Loading

0 comments on commit bbd9d6f

Please sign in to comment.