static int lookup_and_delete_xattr(struct inode *inode, const char *name) { int err = 0; struct dentry *dentry, *xadir; xadir = open_xa_dir(inode, XATTR_REPLACE); if (IS_ERR(xadir)) return PTR_ERR(xadir); mutex_lock_nested(&xadir->d_inode->i_mutex, I_MUTEX_XATTR); dentry = lookup_one_len(name, xadir, strlen(name)); if (IS_ERR(dentry)) { err = PTR_ERR(dentry); goto out_dput; } if (dentry->d_inode) { reiserfs_write_lock(inode->i_sb); err = xattr_unlink(xadir->d_inode, dentry); reiserfs_write_unlock(inode->i_sb); update_ctime(inode); } dput(dentry); out_dput: mutex_unlock(&xadir->d_inode->i_mutex); dput(xadir); return err; }
/* * Inode operation listxattr() * * We totally ignore the generic listxattr here because it would be stupid * not to. Since the xattrs are organized in a directory, we can just * readdir to find them. */ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) { struct dentry *dir; int err = 0; loff_t pos = 0; struct listxattr_buf buf = { .dentry = dentry, .buf = buffer, .size = buffer ? size : 0, }; if (!dentry->d_inode) return -EINVAL; if (!dentry->d_sb->s_xattr || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) return -EOPNOTSUPP; dir = open_xa_dir(dentry->d_inode, XATTR_REPLACE); if (IS_ERR(dir)) { err = PTR_ERR(dir); if (err == -ENODATA) err = 0; /* Not an error if there aren't any xattrs */ goto out; } mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR); err = reiserfs_readdir_dentry(dir, &buf, listxattr_filler, &pos); mutex_unlock(&dir->d_inode->i_mutex); if (!err) err = buf.pos; dput(dir); out: return err; } static int create_privroot(struct dentry *dentry) { int err; struct inode *inode = dentry->d_parent->d_inode; WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex)); err = xattr_mkdir(inode, dentry, 0700); if (err || !dentry->d_inode) { reiserfs_warning(dentry->d_sb, "jdm-20006", "xattrs/ACLs enabled and couldn't " "find/create .reiserfs_priv. " "Failing mount."); return -EOPNOTSUPP; } dentry->d_inode->i_flags |= S_PRIVATE; reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr " "storage.\n", PRIVROOT_NAME); return 0; }
/* Returns a dentry corresponding to a specific extended attribute file * for the inode. If flags allow, the file is created. Otherwise, a * valid or negative dentry, or an error is returned. */ static struct dentry *xattr_lookup(struct inode *inode, const char *name, int flags) { struct dentry *xadir, *xafile; int err = 0; xadir = open_xa_dir(inode, flags); if (IS_ERR(xadir)) return ERR_CAST(xadir); mutex_lock_nested(&xadir->d_inode->i_mutex, I_MUTEX_XATTR); xafile = lookup_one_len(name, xadir, strlen(name)); if (IS_ERR(xafile)) { err = PTR_ERR(xafile); goto out; } if (xafile->d_inode && (flags & XATTR_CREATE)) err = -EEXIST; if (!xafile->d_inode) { err = -ENODATA; if (xattr_may_create(flags)) err = xattr_create(xadir->d_inode, xafile, 0700|S_IFREG); } if (err) dput(xafile); out: mutex_unlock(&xadir->d_inode->i_mutex); dput(xadir); if (err) return ERR_PTR(err); return xafile; }
/* * Inode operation listxattr() * * We totally ignore the generic listxattr here because it would be stupid * not to. Since the xattrs are organized in a directory, we can just * readdir to find them. */ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) { struct dentry *dir; int err = 0; loff_t pos = 0; struct listxattr_buf buf = { .dentry = dentry, .buf = buffer, .size = buffer ? size : 0, }; if (!dentry->d_inode) return -EINVAL; if (!dentry->d_sb->s_xattr || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) return -EOPNOTSUPP; dir = open_xa_dir(dentry->d_inode, XATTR_REPLACE); if (IS_ERR(dir)) { err = PTR_ERR(dir); if (err == -ENODATA) err = 0; /* Not an error if there aren't any xattrs */ goto out; } mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR); err = reiserfs_readdir_dentry(dir, &buf, listxattr_filler, &pos); mutex_unlock(&dir->d_inode->i_mutex); if (!err) err = buf.pos; dput(dir); out: return err; } static int reiserfs_check_acl(struct inode *inode, int mask, unsigned int flags) { struct posix_acl *acl; int error = -EAGAIN; /* do regular unix permission checks by default */ if (flags & IPERM_FLAG_RCU) return -ECHILD; acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); if (acl) { if (!IS_ERR(acl)) { error = posix_acl_permission(inode, acl, mask); posix_acl_release(acl); } else if (PTR_ERR(acl) != -ENODATA) error = PTR_ERR(acl); } return error; } static int create_privroot(struct dentry *dentry) { int err; struct inode *inode = dentry->d_parent->d_inode; WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex)); err = xattr_mkdir(inode, dentry, 0700); if (err || !dentry->d_inode) { reiserfs_warning(dentry->d_sb, "jdm-20006", "xattrs/ACLs enabled and couldn't " "find/create .reiserfs_priv. " "Failing mount."); return -EOPNOTSUPP; } dentry->d_inode->i_flags |= S_PRIVATE; reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr " "storage.\n", PRIVROOT_NAME); return 0; }
static int reiserfs_for_each_xattr(struct inode *inode, int (*action)(struct dentry *, void *), void *data) { struct dentry *dir; int i, err = 0; loff_t pos = 0; struct reiserfs_dentry_buf buf = { .count = 0, }; /* Skip out, an xattr has no xattrs associated with it */ if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1) return 0; reiserfs_write_unlock(inode->i_sb); dir = open_xa_dir(inode, XATTR_REPLACE); if (IS_ERR(dir)) { err = PTR_ERR(dir); reiserfs_write_lock(inode->i_sb); goto out; } else if (!dir->d_inode) { err = 0; reiserfs_write_lock(inode->i_sb); goto out_dir; } mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR); reiserfs_write_lock(inode->i_sb); buf.xadir = dir; err = reiserfs_readdir_dentry(dir, &buf, fill_with_dentries, &pos); while ((err == 0 || err == -ENOSPC) && buf.count) { err = 0; for (i = 0; i < buf.count && buf.dentries[i]; i++) { int lerr = 0; struct dentry *dentry = buf.dentries[i]; if (err == 0 && !S_ISDIR(dentry->d_inode->i_mode)) lerr = action(dentry, data); dput(dentry); buf.dentries[i] = NULL; err = lerr ?: err; } buf.count = 0; if (!err) err = reiserfs_readdir_dentry(dir, &buf, fill_with_dentries, &pos); } mutex_unlock(&dir->d_inode->i_mutex); /* Clean up after a failed readdir */ cleanup_dentry_buf(&buf); if (!err) { /* We start a transaction here to avoid a ABBA situation * between the xattr root's i_mutex and the journal lock. * This doesn't incur much additional overhead since the * new transaction will just nest inside the * outer transaction. */ int blocks = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 4 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb); struct reiserfs_transaction_handle th; err = journal_begin(&th, inode->i_sb, blocks); if (!err) { int jerror; reiserfs_mutex_lock_nested_safe( &dir->d_parent->d_inode->i_mutex, I_MUTEX_XATTR, inode->i_sb); err = action(dir, data); jerror = journal_end(&th, inode->i_sb, blocks); mutex_unlock(&dir->d_parent->d_inode->i_mutex); err = jerror ?: err; } }