From: Chris Mason <chris.mason@oracle.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: torvalds@linux-foundation.org, linux-fsdevel@vger.kernel.org
Subject: Re: [PATCH 01/35] Btrfs xattr code
Date: Tue, 13 Jan 2009 09:37:53 -0500 [thread overview]
Message-ID: <1231857473.29164.27.camel@think.oraclecorp.com> (raw)
In-Reply-To: <20090112205904.c9e11d85.akpm@linux-foundation.org>
On Mon, 2009-01-12 at 20:59 -0800, Andrew Morton wrote:
> On Wed, 7 Jan 2009 22:56:51 -0500 Chris Mason
> <chris.mason@oracle.com> wrote:
>
> > + ret = -ENODATA;
> > + goto out;
> > + }
> > +
> > + leaf = path->nodes[0];
> > + /* if size is 0, that means we want the size of the attr */
> > + if (!size) {
> > + ret = btrfs_dir_data_len(leaf, di);
> > + goto out;
> > + }
> > +
> > + /* now get the data out of our dir_item */
> > + if (btrfs_dir_data_len(leaf, di) > size) {
>
> OK, where did we hide the btrfs_dir_data_len() definition?
>
I had this strange dream that google airlines was bombing my house with
towels....
ctree.h:
/* struct btrfs_dir_item */
BTRFS_SETGET_FUNCS(dir_data_len, struct btrfs_dir_item, data_len, 16);
BTRFS_SETGET_FUNCS(dir_type, struct btrfs_dir_item, type, 8);
BTRFS_SETGET_FUNCS(dir_name_len, struct btrfs_dir_item, name_len, 16);
BTRFS_SETGET_FUNCS(dir_transid, struct btrfs_dir_item, transid, 64);
The macros that define the SETGET_FUNCS are the ugliest part of btrfs.
They are defined and documented inside struct-funcs.c. In general they
provide access to btree blocks that may be smaller/bigger than a single
page and hide the kmap fun.
Because the kmap fun can be a little slow, performance sensitive loops
can use map_extent_buffer to kmap one of the pages in the extent_buffer
and do their work.
> > + ret = -ERANGE;
> > + goto out;
> > + }
> > + data_ptr = (unsigned long)((char *)(di + 1) +
> > + btrfs_dir_name_len(leaf, di));
> > + read_extent_buffer(leaf, buffer, data_ptr,
> > + btrfs_dir_data_len(leaf, di));
>
> Please document read_extent_buffer().
Will document *extent_buffer*
>
> Please rename read_extent_buffer() to something more appropriate to a
> kernel-wide symbol.
The long term plan was for the extent_buffers to be a generic interface,
so I gave them generic names. Before I can finish that off I need to
fix them to properly work with blocksize != pagesize. They have
supported multi-page btree blocks, but I turned that off for a while to
finish off other things.
If you'd rather see them renamed to btrfs_, I'll do so.
>
> <spies map_private_extent_buffer as well>
>
> Please review all kernel-wide identifiers in btrfs for appropriateness.
>
> I'm scratching my head wondering about this `data_ptr' thing. Is it a
> disk offset? Is it really a pointer to kernel memory? According to
> this code it is indeed a kernel pointer, but it then gets stuffed into
> an unsigned long (wtf?) and then passed to the mysterious
> read_extent_buffer().
The data_ptr is an unsigned long offset into the btree block. If you
think of read_extent_buffer as a fancy memcpy wrapper, data_ptr is the
offset in the buffer to read from.
The code in struct-funcs.c hides that most of the time, casting the
unsigned long into a strict type so that most operations look like they
are happening against a real type.
So for: ret = btrfs_dir_data_len(leaf, di);
leaf is the extent_buffer which holds the btree block in ram, and di is
an offset from zero into that buffer where you can find a directory item
struct. It has been cast into a struct btrfs_dir_item, but it is some
number between 0 and 4096.
(It won't actually be zero since that is the start of the header and no
items are stored in the header).
>
> > + ret = btrfs_dir_data_len(leaf, di);
> > +
> > +out:
> > + btrfs_free_path(path);
> > + return ret;
> > +}
> > +
> > +int __btrfs_setxattr(struct inode *inode, const char *name,
> > + const void *value, size_t size, int flags)
> > +{
> > + struct btrfs_dir_item *di;
> > + struct btrfs_root *root = BTRFS_I(inode)->root;
> > + struct btrfs_trans_handle *trans;
> > + struct btrfs_path *path;
> > + int ret = 0, mod = 0;
> > +
> > + path = btrfs_alloc_path();
> > + if (!path)
> > + return -ENOMEM;
> > +
> > + trans = btrfs_start_transaction(root, 1);
> > + btrfs_set_trans_block_group(trans, inode);
> > +
> > + /* first lets see if we already have this xattr */
>
> let's :)
>
> > + di = btrfs_lookup_xattr(trans, root, path, inode->i_ino, name,
> > + strlen(name), -1);
>
> <wonders what the -1 does>
>
> <goes to the btrfs_lookup_xattr() definition site>
>
I'll replace the -1 with BTRFS_SEARCH_ITEM_DEL, but as Josef said this
tells the searching code to balance for item deletion. Nothing is
actually deleted unless btrfs_del_item is called, but the tree is
prepared for deletion/insertion from the top down, so the initial search
needs to know what the code intends to do.
>
> > + if (IS_ERR(di)) {
> > + ret = PTR_ERR(di);
> > + goto out;
> > + }
> > +
> > + /* ok we already have this xattr, lets remove it */
> > + if (di) {
> > + /* if we want create only exit */
> > + if (flags & XATTR_CREATE) {
> > + ret = -EEXIST;
> > + goto out;
> > + }
> > +
> > + ret = btrfs_delete_one_dir_name(trans, root, path, di);
> > + if (ret)
> > + goto out;
> > + btrfs_release_path(root, path);
> > +
> > + /* if we don't have a value then we are removing the xattr */
> > + if (!value) {
> > + mod = 1;
> > + goto out;
> > + }
> > + } else {
> > + btrfs_release_path(root, path);
> > +
> > + if (flags & XATTR_REPLACE) {
> > + /* we couldn't find the attr to replace */
> > + ret = -ENODATA;
> > + goto out;
> > + }
> > + }
> > +
> > + /* ok we have to create a completely new xattr */
> > + ret = btrfs_insert_xattr_item(trans, root, name, strlen(name),
> > + value, size, inode->i_ino);
> > + if (ret)
> > + goto out;
> > + mod = 1;
> > +
> > +out:
> > + if (mod) {
> > + inode->i_ctime = CURRENT_TIME;
> > + ret = btrfs_update_inode(trans, root, inode);
> > + }
> > +
> > + btrfs_end_transaction(trans, root);
> > + btrfs_free_path(path);
> > + return ret;
> > +}
> > +
> > +ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
> > +{
> > + struct btrfs_key key, found_key;
> > + struct inode *inode = dentry->d_inode;
> > + struct btrfs_root *root = BTRFS_I(inode)->root;
> > + struct btrfs_path *path;
> > + struct btrfs_item *item;
> > + struct extent_buffer *leaf;
> > + struct btrfs_dir_item *di;
> > + int ret = 0, slot, advance;
> > + size_t total_size = 0, size_left = size;
> > + unsigned long name_ptr;
> > + size_t name_len;
> > + u32 nritems;
> > +
> > + /*
> > + * ok we want all objects associated with this id.
> > + * NOTE: we set key.offset = 0; because we want to start with the
> > + * first xattr that we find and walk forward
> > + */
> > + key.objectid = inode->i_ino;
> > + btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY);
> > + key.offset = 0;
> > +
> > + path = btrfs_alloc_path();
> > + if (!path)
> > + return -ENOMEM;
> > + path->reada = 2;
>
> <gets interested in btrfs_path.reada>
>
> <greps for a while>
>
> path->reada = 2;
I'll fix this to BTRFS_SEARCH_FORCE_RA
There are three types of metadata ra done. Some funcs need to walk
backwards from a high key to a low key, so that's backwards ra (-1)
The default is to just read blocks that are close to the target block.
The code above is forcing ra because it knows it is going to be walking
forward in the key space.
-chris
next prev parent reply other threads:[~2009-01-13 14:38 UTC|newest]
Thread overview: 58+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-01-08 3:56 [PATCH 00/35] Btrfs for review Chris Mason
2009-01-08 3:56 ` [PATCH 01/35] Btrfs xattr code Chris Mason
2009-01-13 4:59 ` Andrew Morton
2009-01-13 12:56 ` Josef Bacik
2009-01-13 14:37 ` Chris Mason [this message]
2009-01-08 3:56 ` [PATCH 02/35] Btrfs multi-device code Chris Mason
2009-01-13 6:23 ` Andrew Morton
2009-01-13 16:36 ` Chris Mason
2009-01-13 17:52 ` Andrew Morton
2009-01-13 17:58 ` Chris Mason
2009-01-30 15:09 ` Andy Whitcroft
2009-01-08 3:56 ` [PATCH 03/35] Btrfs tree logging (fsync optimizations) Chris Mason
2009-01-08 3:56 ` [PATCH 04/35] Btrfs transaction code Chris Mason
2009-01-08 3:56 ` [PATCH 05/35] Btrfs btree leaf reference cache Chris Mason
2009-01-08 3:56 ` [PATCH 06/35] Btrfs tree printk debugging Chris Mason
2009-01-08 3:56 ` [PATCH 07/35] Btrfs ordered data processing Chris Mason
2009-01-08 3:56 ` [PATCH 08/35] Btrfs btree locking helpers Chris Mason
2009-01-08 3:56 ` [PATCH 09/35] Btrfs zlib helpers Chris Mason
2009-01-08 3:57 ` [PATCH 10/35] Btrfs online btree defragging Chris Mason
2009-01-08 3:57 ` [PATCH 11/35] Btrfs sysfs routines Chris Mason
2009-01-08 3:57 ` [PATCH 12/35] Btrfs super operations Chris Mason
2009-01-08 3:57 ` [PATCH 13/35] Btrfs metadata access routines Chris Mason
2009-01-08 3:57 ` [PATCH 14/35] Btrfs tree of tree roots code Chris Mason
2009-01-08 3:57 ` [PATCH 15/35] Btrfs Orphan prevention Chris Mason
2009-01-08 3:57 ` [PATCH 16/35] Btrfs free inode allocation Chris Mason
2009-01-08 3:57 ` [PATCH 17/35] Btrfs inode item routines Chris Mason
2009-01-08 3:57 ` [PATCH 19/35] Btrfs directory name hashing Chris Mason
2009-01-08 3:57 ` [PATCH 20/35] Btrfs free space caching Chris Mason
2009-01-08 3:57 ` [PATCH 21/35] Btrfs file-item and checksumming routines Chris Mason
2009-01-08 3:57 ` [PATCH 22/35] Btrfs file write routines Chris Mason
2009-01-08 3:57 ` [PATCH 24/35] Btrfs directory item routines Chris Mason
2009-01-08 3:57 ` [PATCH 25/35] Btrfs main metadata header file Chris Mason
2009-01-08 3:57 ` [PATCH 27/35] Btrfs in-memory inode.h Chris Mason
2009-01-08 3:57 ` [PATCH 28/35] Btrfs acl implementation Chris Mason
2009-01-08 3:57 ` [PATCH 29/35] Btrfs ioctl code Chris Mason
2009-01-15 18:29 ` Ryusuke Konishi
2009-01-15 20:17 ` Linus Torvalds
2009-01-15 20:28 ` Chris Mason
2009-01-15 20:44 ` Linus Torvalds
2009-01-15 20:49 ` Chris Mason
2009-01-16 17:23 ` Chris Mason
2009-01-17 4:16 ` Ryusuke Konishi
2009-01-08 3:57 ` [PATCH 30/35] Btrfs extent_map: per-file extent lookup cache Chris Mason
2009-01-08 3:57 ` [PATCH 32/35] Btrfs NFS exporting routines Chris Mason
2009-01-08 3:57 ` [PATCH 33/35] Btrfs metadata disk-io routines Chris Mason
2009-01-08 3:57 ` [PATCH 34/35] Btrfs compression routines Chris Mason
2009-01-08 3:57 ` [PATCH 35/35] Async thread routines Chris Mason
2009-01-08 16:01 ` [PATCH 18.1/35] Btrfs inode operations Chris Mason
2009-01-08 16:04 ` [PATCH 18.2/35] Btrfs inode extent_io hooks Chris Mason
2009-01-08 16:06 ` [PATCH 23.1/35] Btrfs extent allocation code Chris Mason
2009-01-08 16:07 ` [PATCH 23.2/35] Btrfs snapshot deletion Chris Mason
2009-01-08 16:08 ` [PATCH 23.3/35] Btrfs extent relocation Chris Mason
2009-01-08 16:10 ` [PATCH 26.1/35] Btrfs btree core Chris Mason
2009-01-08 16:11 ` [PATCH 26.2/35] Btrfs btree item routines Chris Mason
2009-01-08 16:12 ` [PATCH 31.1/35] Btrfs extent io operations Chris Mason
2009-01-08 16:13 ` [PATCH 31.2/35] Btrfs extent_buffer code Chris Mason
2009-01-09 2:28 ` [PATCH 00/35] Btrfs for review Andi Kleen
2009-01-09 21:13 ` Chris Mason
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1231857473.29164.27.camel@think.oraclecorp.com \
--to=chris.mason@oracle.com \
--cc=akpm@linux-foundation.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.