/* * 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; struct listxattr_buf buf = { .ctx.actor = listxattr_filler, .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_inode(dir->d_inode, &buf.ctx); 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; }
static int reiserfs_for_each_xattr(struct inode *inode, int (*action)(struct dentry *, void *), void *data) { struct dentry *dir; int i, err = 0; struct reiserfs_dentry_buf buf = { .ctx.actor = fill_with_dentries, }; /* Skip out, an xattr has no xattrs associated with it */ if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1) return 0; dir = open_xa_dir(inode, XATTR_REPLACE); if (IS_ERR(dir)) { err = PTR_ERR(dir); goto out; } else if (!dir->d_inode) { err = 0; goto out_dir; } mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR); buf.xadir = dir; while (1) { err = reiserfs_readdir_inode(dir->d_inode, &buf.ctx); if (err) break; if (!buf.count) break; for (i = 0; !err && i < buf.count && buf.dentries[i]; i++) { struct dentry *dentry = buf.dentries[i]; if (!S_ISDIR(dentry->d_inode->i_mode)) err = action(dentry, data); dput(dentry); buf.dentries[i] = NULL; } if (err) break; buf.count = 0; } mutex_unlock(&dir->d_inode->i_mutex); 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; reiserfs_write_lock(inode->i_sb); err = journal_begin(&th, inode->i_sb, blocks); reiserfs_write_unlock(inode->i_sb); if (!err) { int jerror; mutex_lock_nested(&dir->d_parent->d_inode->i_mutex, I_MUTEX_XATTR); err = action(dir, data); reiserfs_write_lock(inode->i_sb); jerror = journal_end(&th, inode->i_sb, blocks); reiserfs_write_unlock(inode->i_sb); mutex_unlock(&dir->d_parent->d_inode->i_mutex); err = jerror ?: err; } }
static int reiserfs_readdir(struct file *file, struct dir_context *ctx) { return reiserfs_readdir_inode(file_inode(file), ctx); }