*/
#include <linux/reiserfs_fs.h>
+#include <linux/capability.h>
#include <linux/dcache.h>
#include <linux/namei.h>
#include <linux/errno.h>
goto out;
} else if (!xaroot->d_inode) {
int err;
- down(&privroot->d_inode->i_sem);
+ mutex_lock(&privroot->d_inode->i_mutex);
err =
privroot->d_inode->i_op->mkdir(privroot->d_inode, xaroot,
0700);
- up(&privroot->d_inode->i_sem);
+ mutex_unlock(&privroot->d_inode->i_mutex);
if (err) {
dput(xaroot);
} else if (flags & XATTR_REPLACE || flags & FL_READONLY) {
goto out;
} else {
- /* inode->i_sem is down, so nothing else can try to create
+ /* inode->i_mutex is down, so nothing else can try to create
* the same xattr */
err = xadir->d_inode->i_op->create(xadir->d_inode, xafile,
0700 | S_IFREG, NULL);
* and don't mess with f->f_pos, but the idea is the same. Do some
* action on each and every entry in the directory.
*
- * we're called with i_sem held, so there are no worries about the directory
+ * we're called with i_mutex held, so there are no worries about the directory
* changing underneath us.
*/
static int __xattr_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (d_reclen <= 32) {
local_buf = small_buf;
} else {
- local_buf =
- reiserfs_kmalloc(d_reclen, GFP_NOFS, inode->i_sb);
+ local_buf = kmalloc(d_reclen, GFP_NOFS);
if (!local_buf) {
pathrelse(&path_to_entry);
return -ENOMEM;
}
if (item_moved(&tmp_ih, &path_to_entry)) {
- reiserfs_kfree(local_buf, d_reclen,
- inode->i_sb);
+ kfree(local_buf);
/* sigh, must retry. Do this same offset again */
next_pos = d_off;
if (filldir(dirent, local_buf, d_reclen, d_off, d_ino,
DT_UNKNOWN) < 0) {
if (local_buf != small_buf) {
- reiserfs_kfree(local_buf, d_reclen,
- inode->i_sb);
+ kfree(local_buf);
}
goto end;
}
if (local_buf != small_buf) {
- reiserfs_kfree(local_buf, d_reclen, inode->i_sb);
+ kfree(local_buf);
}
} /* while */
int res = -ENOTDIR;
if (!file->f_op || !file->f_op->readdir)
goto out;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
// down(&inode->i_zombie);
res = -ENOENT;
if (!IS_DEADDIR(inode)) {
unlock_kernel();
}
// up(&inode->i_zombie);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
out:
return res;
}
/* We can deadlock if we try to free dentries,
and an unlink/rmdir has just occured - GFP_NOFS avoids this */
mapping_set_gfp_mask(mapping, GFP_NOFS);
- page = read_cache_page(mapping, n,
- (filler_t *) mapping->a_ops->readpage, NULL);
+ page = read_mapping_page(mapping, n, NULL);
if (!IS_ERR(page)) {
wait_on_page_locked(page);
kmap(page);
/* Generic extended attribute operations that can be used by xa plugins */
/*
- * inode->i_sem: down
+ * inode->i_mutex: down
*/
int
reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
struct iattr newattrs;
__u32 xahash = 0;
- if (IS_RDONLY(inode))
- return -EROFS;
-
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
- return -EPERM;
-
if (get_inode_sd_version(inode) == STAT_DATA_V1)
return -EOPNOTSUPP;
/* Resize it so we're ok to write there */
newattrs.ia_size = buffer_size;
newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
- down(&xinode->i_sem);
+ mutex_lock(&xinode->i_mutex);
err = notify_change(fp->f_dentry, &newattrs);
if (err)
goto out_filp;
}
out_filp:
- up(&xinode->i_sem);
+ mutex_unlock(&xinode->i_mutex);
fput(fp);
out:
}
/*
- * inode->i_sem: down
+ * inode->i_mutex: down
*/
int
reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer,
struct dentry *dir;
int err;
- if (IS_RDONLY(inode))
- return -EROFS;
-
dir = open_xa_dir(inode, FL_READONLY);
if (IS_ERR(dir)) {
err = PTR_ERR(dir);
}
-/* This is called w/ inode->i_sem downed */
+/* This is called w/ inode->i_mutex downed */
int reiserfs_delete_xattrs(struct inode *inode)
{
struct file *fp;
/*
* Inode operation getxattr()
- * Preliminary locking: we down dentry->d_inode->i_sem
+ * Preliminary locking: we down dentry->d_inode->i_mutex
*/
ssize_t
reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer,
/*
* Inode operation setxattr()
*
- * dentry->d_inode->i_sem down
+ * dentry->d_inode->i_mutex down
*/
int
reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
return -EOPNOTSUPP;
- if (IS_RDONLY(dentry->d_inode))
- return -EROFS;
-
- if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode))
- return -EROFS;
-
reiserfs_write_lock_xattr_i(dentry->d_inode);
lock = !has_xattr_dir(dentry->d_inode);
if (lock)
/*
* Inode operation removexattr()
*
- * dentry->d_inode->i_sem down
+ * dentry->d_inode->i_mutex down
*/
int reiserfs_removexattr(struct dentry *dentry, const char *name)
{
get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
return -EOPNOTSUPP;
- if (IS_RDONLY(dentry->d_inode))
- return -EROFS;
-
- if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode))
- return -EPERM;
-
reiserfs_write_lock_xattr_i(dentry->d_inode);
reiserfs_read_lock_xattrs(dentry->d_sb);
/*
* Inode operation listxattr()
*
- * Preliminary locking: we down dentry->d_inode->i_sem
+ * Preliminary locking: we down dentry->d_inode->i_mutex
*/
ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size)
{
if (!IS_ERR(dentry)) {
if (!(mount_flags & MS_RDONLY) && !dentry->d_inode) {
struct inode *inode = dentry->d_parent->d_inode;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
err = inode->i_op->mkdir(inode, dentry, 0700);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
if (err) {
dput(dentry);
dentry = NULL;
return err;
}
-static int
-__reiserfs_permission(struct inode *inode, int mask, struct nameidata *nd,
- int need_lock)
+static int reiserfs_check_acl(struct inode *inode, int mask)
{
- umode_t mode = inode->i_mode;
+ struct posix_acl *acl;
+ int error = -EAGAIN; /* do regular unix permission checks by default */
- if (mask & MAY_WRITE) {
- /*
- * Nobody gets write access to a read-only fs.
- */
- if (IS_RDONLY(inode) &&
- (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
- return -EROFS;
-
- /*
- * Nobody gets write access to an immutable file.
- */
- if (IS_IMMUTABLE(inode))
- return -EACCES;
- }
+ reiserfs_read_lock_xattr_i(inode);
+ reiserfs_read_lock_xattrs(inode->i_sb);
- /* We don't do permission checks on the internal objects.
- * Permissions are determined by the "owning" object. */
- if (is_reiserfs_priv_object(inode))
- return 0;
+ acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
- if (current->fsuid == inode->i_uid) {
- mode >>= 6;
-#ifdef CONFIG_REISERFS_FS_POSIX_ACL
- } else if (reiserfs_posixacl(inode->i_sb) &&
- get_inode_sd_version(inode) != STAT_DATA_V1) {
- struct posix_acl *acl;
-
- /* ACL can't contain additional permissions if
- the ACL_MASK entry is 0 */
- if (!(mode & S_IRWXG))
- goto check_groups;
-
- if (need_lock) {
- reiserfs_read_lock_xattr_i(inode);
- reiserfs_read_lock_xattrs(inode->i_sb);
- }
- acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
- if (need_lock) {
- reiserfs_read_unlock_xattrs(inode->i_sb);
- reiserfs_read_unlock_xattr_i(inode);
- }
- if (IS_ERR(acl)) {
- if (PTR_ERR(acl) == -ENODATA)
- goto check_groups;
- return PTR_ERR(acl);
- }
+ reiserfs_read_unlock_xattrs(inode->i_sb);
+ reiserfs_read_unlock_xattr_i(inode);
- if (acl) {
- int err = posix_acl_permission(inode, acl, mask);
+ if (acl) {
+ if (!IS_ERR(acl)) {
+ error = posix_acl_permission(inode, acl, mask);
posix_acl_release(acl);
- if (err == -EACCES) {
- goto check_capabilities;
- }
- return err;
- } else {
- goto check_groups;
- }
-#endif
- } else {
- check_groups:
- if (in_group_p(inode->i_gid))
- mode >>= 3;
+ } else if (PTR_ERR(acl) != -ENODATA)
+ error = PTR_ERR(acl);
}
- /*
- * If the DACs are ok we don't need any capability check.
- */
- if (((mode & mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == mask))
- return 0;
+ return error;
+}
- check_capabilities:
+int reiserfs_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
/*
- * Read/write DACs are always overridable.
- * Executable DACs are overridable if at least one exec bit is set.
+ * We don't do permission checks on the internal objects.
+ * Permissions are determined by the "owning" object.
*/
- if (!(mask & MAY_EXEC) ||
- (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode))
- if (capable(CAP_DAC_OVERRIDE))
- return 0;
+ if (is_reiserfs_priv_object(inode))
+ return 0;
/*
- * Searching includes executable on directories, else just read.
+ * Stat data v1 doesn't support ACLs.
*/
- if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE)))
- if (capable(CAP_DAC_READ_SEARCH))
- return 0;
-
- return -EACCES;
-}
-
-int reiserfs_permission(struct inode *inode, int mask, struct nameidata *nd)
-{
- return __reiserfs_permission(inode, mask, nd, 1);
-}
-
-int
-reiserfs_permission_locked(struct inode *inode, int mask, struct nameidata *nd)
-{
- return __reiserfs_permission(inode, mask, nd, 0);
+ if (get_inode_sd_version(inode) == STAT_DATA_V1)
+ return generic_permission(inode, mask, NULL);
+ else
+ return generic_permission(inode, mask, reiserfs_check_acl);
}