diff options
Diffstat (limited to 'fs/btrfs/xattr.c')
-rw-r--r-- | fs/btrfs/xattr.c | 67 |
1 files changed, 42 insertions, 25 deletions
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 6c68d6356197..145d2b89e62d 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c | |||
@@ -249,7 +249,7 @@ int __btrfs_setxattr(struct btrfs_trans_handle *trans, | |||
249 | goto out; | 249 | goto out; |
250 | 250 | ||
251 | inode_inc_iversion(inode); | 251 | inode_inc_iversion(inode); |
252 | inode->i_ctime = CURRENT_TIME; | 252 | inode->i_ctime = current_fs_time(inode->i_sb); |
253 | set_bit(BTRFS_INODE_COPY_EVERYTHING, &BTRFS_I(inode)->runtime_flags); | 253 | set_bit(BTRFS_INODE_COPY_EVERYTHING, &BTRFS_I(inode)->runtime_flags); |
254 | ret = btrfs_update_inode(trans, root, inode); | 254 | ret = btrfs_update_inode(trans, root, inode); |
255 | BUG_ON(ret); | 255 | BUG_ON(ret); |
@@ -260,16 +260,12 @@ out: | |||
260 | 260 | ||
261 | ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) | 261 | ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) |
262 | { | 262 | { |
263 | struct btrfs_key key, found_key; | 263 | struct btrfs_key key; |
264 | struct inode *inode = d_inode(dentry); | 264 | struct inode *inode = d_inode(dentry); |
265 | struct btrfs_root *root = BTRFS_I(inode)->root; | 265 | struct btrfs_root *root = BTRFS_I(inode)->root; |
266 | struct btrfs_path *path; | 266 | struct btrfs_path *path; |
267 | struct extent_buffer *leaf; | 267 | int ret = 0; |
268 | struct btrfs_dir_item *di; | ||
269 | int ret = 0, slot; | ||
270 | size_t total_size = 0, size_left = size; | 268 | size_t total_size = 0, size_left = size; |
271 | unsigned long name_ptr; | ||
272 | size_t name_len; | ||
273 | 269 | ||
274 | /* | 270 | /* |
275 | * ok we want all objects associated with this id. | 271 | * ok we want all objects associated with this id. |
@@ -291,6 +287,13 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) | |||
291 | goto err; | 287 | goto err; |
292 | 288 | ||
293 | while (1) { | 289 | while (1) { |
290 | struct extent_buffer *leaf; | ||
291 | int slot; | ||
292 | struct btrfs_dir_item *di; | ||
293 | struct btrfs_key found_key; | ||
294 | u32 item_size; | ||
295 | u32 cur; | ||
296 | |||
294 | leaf = path->nodes[0]; | 297 | leaf = path->nodes[0]; |
295 | slot = path->slots[0]; | 298 | slot = path->slots[0]; |
296 | 299 | ||
@@ -316,31 +319,45 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) | |||
316 | if (found_key.type > BTRFS_XATTR_ITEM_KEY) | 319 | if (found_key.type > BTRFS_XATTR_ITEM_KEY) |
317 | break; | 320 | break; |
318 | if (found_key.type < BTRFS_XATTR_ITEM_KEY) | 321 | if (found_key.type < BTRFS_XATTR_ITEM_KEY) |
319 | goto next; | 322 | goto next_item; |
320 | 323 | ||
321 | di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); | 324 | di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); |
322 | if (verify_dir_item(root, leaf, di)) | 325 | item_size = btrfs_item_size_nr(leaf, slot); |
323 | goto next; | 326 | cur = 0; |
324 | 327 | while (cur < item_size) { | |
325 | name_len = btrfs_dir_name_len(leaf, di); | 328 | u16 name_len = btrfs_dir_name_len(leaf, di); |
326 | total_size += name_len + 1; | 329 | u16 data_len = btrfs_dir_data_len(leaf, di); |
330 | u32 this_len = sizeof(*di) + name_len + data_len; | ||
331 | unsigned long name_ptr = (unsigned long)(di + 1); | ||
332 | |||
333 | if (verify_dir_item(root, leaf, di)) { | ||
334 | ret = -EIO; | ||
335 | goto err; | ||
336 | } | ||
327 | 337 | ||
328 | /* we are just looking for how big our buffer needs to be */ | 338 | total_size += name_len + 1; |
329 | if (!size) | 339 | /* |
330 | goto next; | 340 | * We are just looking for how big our buffer needs to |
341 | * be. | ||
342 | */ | ||
343 | if (!size) | ||
344 | goto next; | ||
331 | 345 | ||
332 | if (!buffer || (name_len + 1) > size_left) { | 346 | if (!buffer || (name_len + 1) > size_left) { |
333 | ret = -ERANGE; | 347 | ret = -ERANGE; |
334 | goto err; | 348 | goto err; |
335 | } | 349 | } |
336 | 350 | ||
337 | name_ptr = (unsigned long)(di + 1); | 351 | read_extent_buffer(leaf, buffer, name_ptr, name_len); |
338 | read_extent_buffer(leaf, buffer, name_ptr, name_len); | 352 | buffer[name_len] = '\0'; |
339 | buffer[name_len] = '\0'; | ||
340 | 353 | ||
341 | size_left -= name_len + 1; | 354 | size_left -= name_len + 1; |
342 | buffer += name_len + 1; | 355 | buffer += name_len + 1; |
343 | next: | 356 | next: |
357 | cur += this_len; | ||
358 | di = (struct btrfs_dir_item *)((char *)di + this_len); | ||
359 | } | ||
360 | next_item: | ||
344 | path->slots[0]++; | 361 | path->slots[0]++; |
345 | } | 362 | } |
346 | ret = total_size; | 363 | ret = total_size; |