11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Copyright (C) International Business Machines Corp., 2000-2004 31da177e4SLinus Torvalds * Copyright (C) Christoph Hellwig, 2002 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 61da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 71da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 81da177e4SLinus Torvalds * (at your option) any later version. 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, 111da177e4SLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 121da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 131da177e4SLinus Torvalds * the GNU General Public License for more details. 141da177e4SLinus Torvalds * 151da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License 161da177e4SLinus Torvalds * along with this program; if not, write to the Free Software 171da177e4SLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 181da177e4SLinus Torvalds */ 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds #include <linux/fs.h> 211da177e4SLinus Torvalds #include <linux/xattr.h> 229a59f452SChristoph Hellwig #include <linux/posix_acl_xattr.h> 231da177e4SLinus Torvalds #include <linux/quotaops.h> 241d15b10fSDave Kleikamp #include <linux/security.h> 251da177e4SLinus Torvalds #include "jfs_incore.h" 261da177e4SLinus Torvalds #include "jfs_superblock.h" 271da177e4SLinus Torvalds #include "jfs_dmap.h" 281da177e4SLinus Torvalds #include "jfs_debug.h" 291da177e4SLinus Torvalds #include "jfs_dinode.h" 301da177e4SLinus Torvalds #include "jfs_extent.h" 311da177e4SLinus Torvalds #include "jfs_metapage.h" 321da177e4SLinus Torvalds #include "jfs_xattr.h" 331da177e4SLinus Torvalds #include "jfs_acl.h" 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds /* 361da177e4SLinus Torvalds * jfs_xattr.c: extended attribute service 371da177e4SLinus Torvalds * 381da177e4SLinus Torvalds * Overall design -- 391da177e4SLinus Torvalds * 401da177e4SLinus Torvalds * Format: 411da177e4SLinus Torvalds * 421da177e4SLinus Torvalds * Extended attribute lists (jfs_ea_list) consist of an overall size (32 bit 431da177e4SLinus Torvalds * value) and a variable (0 or more) number of extended attribute 441da177e4SLinus Torvalds * entries. Each extended attribute entry (jfs_ea) is a <name,value> double 451da177e4SLinus Torvalds * where <name> is constructed from a null-terminated ascii string 461da177e4SLinus Torvalds * (1 ... 255 bytes in the name) and <value> is arbitrary 8 bit data 471da177e4SLinus Torvalds * (1 ... 65535 bytes). The in-memory format is 481da177e4SLinus Torvalds * 491da177e4SLinus Torvalds * 0 1 2 4 4 + namelen + 1 501da177e4SLinus Torvalds * +-------+--------+--------+----------------+-------------------+ 511da177e4SLinus Torvalds * | Flags | Name | Value | Name String \0 | Data . . . . | 521da177e4SLinus Torvalds * | | Length | Length | | | 531da177e4SLinus Torvalds * +-------+--------+--------+----------------+-------------------+ 541da177e4SLinus Torvalds * 551da177e4SLinus Torvalds * A jfs_ea_list then is structured as 561da177e4SLinus Torvalds * 571da177e4SLinus Torvalds * 0 4 4 + EA_SIZE(ea1) 581da177e4SLinus Torvalds * +------------+-------------------+--------------------+----- 591da177e4SLinus Torvalds * | Overall EA | First FEA Element | Second FEA Element | ..... 601da177e4SLinus Torvalds * | List Size | | | 611da177e4SLinus Torvalds * +------------+-------------------+--------------------+----- 621da177e4SLinus Torvalds * 631da177e4SLinus Torvalds * On-disk: 641da177e4SLinus Torvalds * 651da177e4SLinus Torvalds * FEALISTs are stored on disk using blocks allocated by dbAlloc() and 661da177e4SLinus Torvalds * written directly. An EA list may be in-lined in the inode if there is 671da177e4SLinus Torvalds * sufficient room available. 681da177e4SLinus Torvalds */ 691da177e4SLinus Torvalds 701da177e4SLinus Torvalds struct ea_buffer { 711da177e4SLinus Torvalds int flag; /* Indicates what storage xattr points to */ 721da177e4SLinus Torvalds int max_size; /* largest xattr that fits in current buffer */ 731da177e4SLinus Torvalds dxd_t new_ea; /* dxd to replace ea when modifying xattr */ 741da177e4SLinus Torvalds struct metapage *mp; /* metapage containing ea list */ 751da177e4SLinus Torvalds struct jfs_ea_list *xattr; /* buffer containing ea list */ 761da177e4SLinus Torvalds }; 771da177e4SLinus Torvalds 781da177e4SLinus Torvalds /* 791da177e4SLinus Torvalds * ea_buffer.flag values 801da177e4SLinus Torvalds */ 811da177e4SLinus Torvalds #define EA_INLINE 0x0001 821da177e4SLinus Torvalds #define EA_EXTENT 0x0002 831da177e4SLinus Torvalds #define EA_NEW 0x0004 841da177e4SLinus Torvalds #define EA_MALLOC 0x0008 851da177e4SLinus Torvalds 861da177e4SLinus Torvalds /* Namespaces */ 871da177e4SLinus Torvalds #define XATTR_SYSTEM_PREFIX "system." 881da177e4SLinus Torvalds #define XATTR_SYSTEM_PREFIX_LEN (sizeof (XATTR_SYSTEM_PREFIX) - 1) 891da177e4SLinus Torvalds 901da177e4SLinus Torvalds #define XATTR_USER_PREFIX "user." 911da177e4SLinus Torvalds #define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1) 921da177e4SLinus Torvalds 931da177e4SLinus Torvalds #define XATTR_OS2_PREFIX "os2." 941da177e4SLinus Torvalds #define XATTR_OS2_PREFIX_LEN (sizeof (XATTR_OS2_PREFIX) - 1) 951da177e4SLinus Torvalds 961da177e4SLinus Torvalds /* XATTR_SECURITY_PREFIX is defined in include/linux/xattr.h */ 971da177e4SLinus Torvalds #define XATTR_SECURITY_PREFIX_LEN (sizeof (XATTR_SECURITY_PREFIX) - 1) 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds #define XATTR_TRUSTED_PREFIX "trusted." 1001da177e4SLinus Torvalds #define XATTR_TRUSTED_PREFIX_LEN (sizeof (XATTR_TRUSTED_PREFIX) - 1) 1011da177e4SLinus Torvalds 1021da177e4SLinus Torvalds /* 1031da177e4SLinus Torvalds * These three routines are used to recognize on-disk extended attributes 1041da177e4SLinus Torvalds * that are in a recognized namespace. If the attribute is not recognized, 1051da177e4SLinus Torvalds * "os2." is prepended to the name 1061da177e4SLinus Torvalds */ 1071da177e4SLinus Torvalds static inline int is_os2_xattr(struct jfs_ea *ea) 1081da177e4SLinus Torvalds { 1091da177e4SLinus Torvalds /* 1101da177e4SLinus Torvalds * Check for "system." 1111da177e4SLinus Torvalds */ 1121da177e4SLinus Torvalds if ((ea->namelen >= XATTR_SYSTEM_PREFIX_LEN) && 1131da177e4SLinus Torvalds !strncmp(ea->name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) 1141da177e4SLinus Torvalds return FALSE; 1151da177e4SLinus Torvalds /* 1161da177e4SLinus Torvalds * Check for "user." 1171da177e4SLinus Torvalds */ 1181da177e4SLinus Torvalds if ((ea->namelen >= XATTR_USER_PREFIX_LEN) && 1191da177e4SLinus Torvalds !strncmp(ea->name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) 1201da177e4SLinus Torvalds return FALSE; 1211da177e4SLinus Torvalds /* 1221da177e4SLinus Torvalds * Check for "security." 1231da177e4SLinus Torvalds */ 1241da177e4SLinus Torvalds if ((ea->namelen >= XATTR_SECURITY_PREFIX_LEN) && 1251da177e4SLinus Torvalds !strncmp(ea->name, XATTR_SECURITY_PREFIX, 1261da177e4SLinus Torvalds XATTR_SECURITY_PREFIX_LEN)) 1271da177e4SLinus Torvalds return FALSE; 1281da177e4SLinus Torvalds /* 1291da177e4SLinus Torvalds * Check for "trusted." 1301da177e4SLinus Torvalds */ 1311da177e4SLinus Torvalds if ((ea->namelen >= XATTR_TRUSTED_PREFIX_LEN) && 1321da177e4SLinus Torvalds !strncmp(ea->name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) 1331da177e4SLinus Torvalds return FALSE; 1341da177e4SLinus Torvalds /* 1351da177e4SLinus Torvalds * Add any other valid namespace prefixes here 1361da177e4SLinus Torvalds */ 1371da177e4SLinus Torvalds 1381da177e4SLinus Torvalds /* 1391da177e4SLinus Torvalds * We assume it's OS/2's flat namespace 1401da177e4SLinus Torvalds */ 1411da177e4SLinus Torvalds return TRUE; 1421da177e4SLinus Torvalds } 1431da177e4SLinus Torvalds 1441da177e4SLinus Torvalds static inline int name_size(struct jfs_ea *ea) 1451da177e4SLinus Torvalds { 1461da177e4SLinus Torvalds if (is_os2_xattr(ea)) 1471da177e4SLinus Torvalds return ea->namelen + XATTR_OS2_PREFIX_LEN; 1481da177e4SLinus Torvalds else 1491da177e4SLinus Torvalds return ea->namelen; 1501da177e4SLinus Torvalds } 1511da177e4SLinus Torvalds 1521da177e4SLinus Torvalds static inline int copy_name(char *buffer, struct jfs_ea *ea) 1531da177e4SLinus Torvalds { 1541da177e4SLinus Torvalds int len = ea->namelen; 1551da177e4SLinus Torvalds 1561da177e4SLinus Torvalds if (is_os2_xattr(ea)) { 1571da177e4SLinus Torvalds memcpy(buffer, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN); 1581da177e4SLinus Torvalds buffer += XATTR_OS2_PREFIX_LEN; 1591da177e4SLinus Torvalds len += XATTR_OS2_PREFIX_LEN; 1601da177e4SLinus Torvalds } 1611da177e4SLinus Torvalds memcpy(buffer, ea->name, ea->namelen); 1621da177e4SLinus Torvalds buffer[ea->namelen] = 0; 1631da177e4SLinus Torvalds 1641da177e4SLinus Torvalds return len; 1651da177e4SLinus Torvalds } 1661da177e4SLinus Torvalds 1671da177e4SLinus Torvalds /* Forward references */ 1681da177e4SLinus Torvalds static void ea_release(struct inode *inode, struct ea_buffer *ea_buf); 1691da177e4SLinus Torvalds 1701da177e4SLinus Torvalds /* 1711da177e4SLinus Torvalds * NAME: ea_write_inline 1721da177e4SLinus Torvalds * 1731da177e4SLinus Torvalds * FUNCTION: Attempt to write an EA inline if area is available 1741da177e4SLinus Torvalds * 1751da177e4SLinus Torvalds * PRE CONDITIONS: 1761da177e4SLinus Torvalds * Already verified that the specified EA is small enough to fit inline 1771da177e4SLinus Torvalds * 1781da177e4SLinus Torvalds * PARAMETERS: 1791da177e4SLinus Torvalds * ip - Inode pointer 1801da177e4SLinus Torvalds * ealist - EA list pointer 1811da177e4SLinus Torvalds * size - size of ealist in bytes 1821da177e4SLinus Torvalds * ea - dxd_t structure to be filled in with necessary EA information 1831da177e4SLinus Torvalds * if we successfully copy the EA inline 1841da177e4SLinus Torvalds * 1851da177e4SLinus Torvalds * NOTES: 1861da177e4SLinus Torvalds * Checks if the inode's inline area is available. If so, copies EA inline 1871da177e4SLinus Torvalds * and sets <ea> fields appropriately. Otherwise, returns failure, EA will 1881da177e4SLinus Torvalds * have to be put into an extent. 1891da177e4SLinus Torvalds * 1901da177e4SLinus Torvalds * RETURNS: 0 for successful copy to inline area; -1 if area not available 1911da177e4SLinus Torvalds */ 1921da177e4SLinus Torvalds static int ea_write_inline(struct inode *ip, struct jfs_ea_list *ealist, 1931da177e4SLinus Torvalds int size, dxd_t * ea) 1941da177e4SLinus Torvalds { 1951da177e4SLinus Torvalds struct jfs_inode_info *ji = JFS_IP(ip); 1961da177e4SLinus Torvalds 1971da177e4SLinus Torvalds /* 1981da177e4SLinus Torvalds * Make sure we have an EA -- the NULL EA list is valid, but you 1991da177e4SLinus Torvalds * can't copy it! 2001da177e4SLinus Torvalds */ 2011da177e4SLinus Torvalds if (ealist && size > sizeof (struct jfs_ea_list)) { 2021da177e4SLinus Torvalds assert(size <= sizeof (ji->i_inline_ea)); 2031da177e4SLinus Torvalds 2041da177e4SLinus Torvalds /* 2051da177e4SLinus Torvalds * See if the space is available or if it is already being 2061da177e4SLinus Torvalds * used for an inline EA. 2071da177e4SLinus Torvalds */ 2081da177e4SLinus Torvalds if (!(ji->mode2 & INLINEEA) && !(ji->ea.flag & DXD_INLINE)) 2091da177e4SLinus Torvalds return -EPERM; 2101da177e4SLinus Torvalds 2111da177e4SLinus Torvalds DXDsize(ea, size); 2121da177e4SLinus Torvalds DXDlength(ea, 0); 2131da177e4SLinus Torvalds DXDaddress(ea, 0); 2141da177e4SLinus Torvalds memcpy(ji->i_inline_ea, ealist, size); 2151da177e4SLinus Torvalds ea->flag = DXD_INLINE; 2161da177e4SLinus Torvalds ji->mode2 &= ~INLINEEA; 2171da177e4SLinus Torvalds } else { 2181da177e4SLinus Torvalds ea->flag = 0; 2191da177e4SLinus Torvalds DXDsize(ea, 0); 2201da177e4SLinus Torvalds DXDlength(ea, 0); 2211da177e4SLinus Torvalds DXDaddress(ea, 0); 2221da177e4SLinus Torvalds 2231da177e4SLinus Torvalds /* Free up INLINE area */ 2241da177e4SLinus Torvalds if (ji->ea.flag & DXD_INLINE) 2251da177e4SLinus Torvalds ji->mode2 |= INLINEEA; 2261da177e4SLinus Torvalds } 2271da177e4SLinus Torvalds 2281da177e4SLinus Torvalds return 0; 2291da177e4SLinus Torvalds } 2301da177e4SLinus Torvalds 2311da177e4SLinus Torvalds /* 2321da177e4SLinus Torvalds * NAME: ea_write 2331da177e4SLinus Torvalds * 2341da177e4SLinus Torvalds * FUNCTION: Write an EA for an inode 2351da177e4SLinus Torvalds * 2361da177e4SLinus Torvalds * PRE CONDITIONS: EA has been verified 2371da177e4SLinus Torvalds * 2381da177e4SLinus Torvalds * PARAMETERS: 2391da177e4SLinus Torvalds * ip - Inode pointer 2401da177e4SLinus Torvalds * ealist - EA list pointer 2411da177e4SLinus Torvalds * size - size of ealist in bytes 2421da177e4SLinus Torvalds * ea - dxd_t structure to be filled in appropriately with where the 2431da177e4SLinus Torvalds * EA was copied 2441da177e4SLinus Torvalds * 2451da177e4SLinus Torvalds * NOTES: Will write EA inline if able to, otherwise allocates blocks for an 2461da177e4SLinus Torvalds * extent and synchronously writes it to those blocks. 2471da177e4SLinus Torvalds * 2481da177e4SLinus Torvalds * RETURNS: 0 for success; Anything else indicates failure 2491da177e4SLinus Torvalds */ 2501da177e4SLinus Torvalds static int ea_write(struct inode *ip, struct jfs_ea_list *ealist, int size, 2511da177e4SLinus Torvalds dxd_t * ea) 2521da177e4SLinus Torvalds { 2531da177e4SLinus Torvalds struct super_block *sb = ip->i_sb; 2541da177e4SLinus Torvalds struct jfs_inode_info *ji = JFS_IP(ip); 2551da177e4SLinus Torvalds struct jfs_sb_info *sbi = JFS_SBI(sb); 2561da177e4SLinus Torvalds int nblocks; 2571da177e4SLinus Torvalds s64 blkno; 2581da177e4SLinus Torvalds int rc = 0, i; 2591da177e4SLinus Torvalds char *cp; 2601da177e4SLinus Torvalds s32 nbytes, nb; 2611da177e4SLinus Torvalds s32 bytes_to_write; 2621da177e4SLinus Torvalds struct metapage *mp; 2631da177e4SLinus Torvalds 2641da177e4SLinus Torvalds /* 2651da177e4SLinus Torvalds * Quick check to see if this is an in-linable EA. Short EAs 2661da177e4SLinus Torvalds * and empty EAs are all in-linable, provided the space exists. 2671da177e4SLinus Torvalds */ 2681da177e4SLinus Torvalds if (!ealist || size <= sizeof (ji->i_inline_ea)) { 2691da177e4SLinus Torvalds if (!ea_write_inline(ip, ealist, size, ea)) 2701da177e4SLinus Torvalds return 0; 2711da177e4SLinus Torvalds } 2721da177e4SLinus Torvalds 2731da177e4SLinus Torvalds /* figure out how many blocks we need */ 2741da177e4SLinus Torvalds nblocks = (size + (sb->s_blocksize - 1)) >> sb->s_blocksize_bits; 2751da177e4SLinus Torvalds 2761da177e4SLinus Torvalds /* Allocate new blocks to quota. */ 2771da177e4SLinus Torvalds if (DQUOT_ALLOC_BLOCK(ip, nblocks)) { 2781da177e4SLinus Torvalds return -EDQUOT; 2791da177e4SLinus Torvalds } 2801da177e4SLinus Torvalds 2811da177e4SLinus Torvalds rc = dbAlloc(ip, INOHINT(ip), nblocks, &blkno); 2821da177e4SLinus Torvalds if (rc) { 2831da177e4SLinus Torvalds /*Rollback quota allocation. */ 2841da177e4SLinus Torvalds DQUOT_FREE_BLOCK(ip, nblocks); 2851da177e4SLinus Torvalds return rc; 2861da177e4SLinus Torvalds } 2871da177e4SLinus Torvalds 2881da177e4SLinus Torvalds /* 2891da177e4SLinus Torvalds * Now have nblocks worth of storage to stuff into the FEALIST. 2901da177e4SLinus Torvalds * loop over the FEALIST copying data into the buffer one page at 2911da177e4SLinus Torvalds * a time. 2921da177e4SLinus Torvalds */ 2931da177e4SLinus Torvalds cp = (char *) ealist; 2941da177e4SLinus Torvalds nbytes = size; 2951da177e4SLinus Torvalds for (i = 0; i < nblocks; i += sbi->nbperpage) { 2961da177e4SLinus Torvalds /* 2971da177e4SLinus Torvalds * Determine how many bytes for this request, and round up to 2981da177e4SLinus Torvalds * the nearest aggregate block size 2991da177e4SLinus Torvalds */ 3001da177e4SLinus Torvalds nb = min(PSIZE, nbytes); 3011da177e4SLinus Torvalds bytes_to_write = 3021da177e4SLinus Torvalds ((((nb + sb->s_blocksize - 1)) >> sb->s_blocksize_bits)) 3031da177e4SLinus Torvalds << sb->s_blocksize_bits; 3041da177e4SLinus Torvalds 3051da177e4SLinus Torvalds if (!(mp = get_metapage(ip, blkno + i, bytes_to_write, 1))) { 3061da177e4SLinus Torvalds rc = -EIO; 3071da177e4SLinus Torvalds goto failed; 3081da177e4SLinus Torvalds } 3091da177e4SLinus Torvalds 3101da177e4SLinus Torvalds memcpy(mp->data, cp, nb); 3111da177e4SLinus Torvalds 3121da177e4SLinus Torvalds /* 3131da177e4SLinus Torvalds * We really need a way to propagate errors for 3141da177e4SLinus Torvalds * forced writes like this one. --hch 3151da177e4SLinus Torvalds * 3161da177e4SLinus Torvalds * (__write_metapage => release_metapage => flush_metapage) 3171da177e4SLinus Torvalds */ 3181da177e4SLinus Torvalds #ifdef _JFS_FIXME 3191da177e4SLinus Torvalds if ((rc = flush_metapage(mp))) { 3201da177e4SLinus Torvalds /* 3211da177e4SLinus Torvalds * the write failed -- this means that the buffer 3221da177e4SLinus Torvalds * is still assigned and the blocks are not being 3231da177e4SLinus Torvalds * used. this seems like the best error recovery 3241da177e4SLinus Torvalds * we can get ... 3251da177e4SLinus Torvalds */ 3261da177e4SLinus Torvalds goto failed; 3271da177e4SLinus Torvalds } 3281da177e4SLinus Torvalds #else 3291da177e4SLinus Torvalds flush_metapage(mp); 3301da177e4SLinus Torvalds #endif 3311da177e4SLinus Torvalds 3321da177e4SLinus Torvalds cp += PSIZE; 3331da177e4SLinus Torvalds nbytes -= nb; 3341da177e4SLinus Torvalds } 3351da177e4SLinus Torvalds 3361da177e4SLinus Torvalds ea->flag = DXD_EXTENT; 3371da177e4SLinus Torvalds DXDsize(ea, le32_to_cpu(ealist->size)); 3381da177e4SLinus Torvalds DXDlength(ea, nblocks); 3391da177e4SLinus Torvalds DXDaddress(ea, blkno); 3401da177e4SLinus Torvalds 3411da177e4SLinus Torvalds /* Free up INLINE area */ 3421da177e4SLinus Torvalds if (ji->ea.flag & DXD_INLINE) 3431da177e4SLinus Torvalds ji->mode2 |= INLINEEA; 3441da177e4SLinus Torvalds 3451da177e4SLinus Torvalds return 0; 3461da177e4SLinus Torvalds 3471da177e4SLinus Torvalds failed: 3481da177e4SLinus Torvalds /* Rollback quota allocation. */ 3491da177e4SLinus Torvalds DQUOT_FREE_BLOCK(ip, nblocks); 3501da177e4SLinus Torvalds 3511da177e4SLinus Torvalds dbFree(ip, blkno, nblocks); 3521da177e4SLinus Torvalds return rc; 3531da177e4SLinus Torvalds } 3541da177e4SLinus Torvalds 3551da177e4SLinus Torvalds /* 3561da177e4SLinus Torvalds * NAME: ea_read_inline 3571da177e4SLinus Torvalds * 3581da177e4SLinus Torvalds * FUNCTION: Read an inlined EA into user's buffer 3591da177e4SLinus Torvalds * 3601da177e4SLinus Torvalds * PARAMETERS: 3611da177e4SLinus Torvalds * ip - Inode pointer 3621da177e4SLinus Torvalds * ealist - Pointer to buffer to fill in with EA 3631da177e4SLinus Torvalds * 3641da177e4SLinus Torvalds * RETURNS: 0 3651da177e4SLinus Torvalds */ 3661da177e4SLinus Torvalds static int ea_read_inline(struct inode *ip, struct jfs_ea_list *ealist) 3671da177e4SLinus Torvalds { 3681da177e4SLinus Torvalds struct jfs_inode_info *ji = JFS_IP(ip); 3691da177e4SLinus Torvalds int ea_size = sizeDXD(&ji->ea); 3701da177e4SLinus Torvalds 3711da177e4SLinus Torvalds if (ea_size == 0) { 3721da177e4SLinus Torvalds ealist->size = 0; 3731da177e4SLinus Torvalds return 0; 3741da177e4SLinus Torvalds } 3751da177e4SLinus Torvalds 3761da177e4SLinus Torvalds /* Sanity Check */ 3771da177e4SLinus Torvalds if ((sizeDXD(&ji->ea) > sizeof (ji->i_inline_ea))) 3781da177e4SLinus Torvalds return -EIO; 3791da177e4SLinus Torvalds if (le32_to_cpu(((struct jfs_ea_list *) &ji->i_inline_ea)->size) 3801da177e4SLinus Torvalds != ea_size) 3811da177e4SLinus Torvalds return -EIO; 3821da177e4SLinus Torvalds 3831da177e4SLinus Torvalds memcpy(ealist, ji->i_inline_ea, ea_size); 3841da177e4SLinus Torvalds return 0; 3851da177e4SLinus Torvalds } 3861da177e4SLinus Torvalds 3871da177e4SLinus Torvalds /* 3881da177e4SLinus Torvalds * NAME: ea_read 3891da177e4SLinus Torvalds * 3901da177e4SLinus Torvalds * FUNCTION: copy EA data into user's buffer 3911da177e4SLinus Torvalds * 3921da177e4SLinus Torvalds * PARAMETERS: 3931da177e4SLinus Torvalds * ip - Inode pointer 3941da177e4SLinus Torvalds * ealist - Pointer to buffer to fill in with EA 3951da177e4SLinus Torvalds * 3961da177e4SLinus Torvalds * NOTES: If EA is inline calls ea_read_inline() to copy EA. 3971da177e4SLinus Torvalds * 3981da177e4SLinus Torvalds * RETURNS: 0 for success; other indicates failure 3991da177e4SLinus Torvalds */ 4001da177e4SLinus Torvalds static int ea_read(struct inode *ip, struct jfs_ea_list *ealist) 4011da177e4SLinus Torvalds { 4021da177e4SLinus Torvalds struct super_block *sb = ip->i_sb; 4031da177e4SLinus Torvalds struct jfs_inode_info *ji = JFS_IP(ip); 4041da177e4SLinus Torvalds struct jfs_sb_info *sbi = JFS_SBI(sb); 4051da177e4SLinus Torvalds int nblocks; 4061da177e4SLinus Torvalds s64 blkno; 4071da177e4SLinus Torvalds char *cp = (char *) ealist; 4081da177e4SLinus Torvalds int i; 4091da177e4SLinus Torvalds int nbytes, nb; 4101da177e4SLinus Torvalds s32 bytes_to_read; 4111da177e4SLinus Torvalds struct metapage *mp; 4121da177e4SLinus Torvalds 4131da177e4SLinus Torvalds /* quick check for in-line EA */ 4141da177e4SLinus Torvalds if (ji->ea.flag & DXD_INLINE) 4151da177e4SLinus Torvalds return ea_read_inline(ip, ealist); 4161da177e4SLinus Torvalds 4171da177e4SLinus Torvalds nbytes = sizeDXD(&ji->ea); 4181da177e4SLinus Torvalds if (!nbytes) { 4191da177e4SLinus Torvalds jfs_error(sb, "ea_read: nbytes is 0"); 4201da177e4SLinus Torvalds return -EIO; 4211da177e4SLinus Torvalds } 4221da177e4SLinus Torvalds 4231da177e4SLinus Torvalds /* 4241da177e4SLinus Torvalds * Figure out how many blocks were allocated when this EA list was 4251da177e4SLinus Torvalds * originally written to disk. 4261da177e4SLinus Torvalds */ 4271da177e4SLinus Torvalds nblocks = lengthDXD(&ji->ea) << sbi->l2nbperpage; 4281da177e4SLinus Torvalds blkno = addressDXD(&ji->ea) << sbi->l2nbperpage; 4291da177e4SLinus Torvalds 4301da177e4SLinus Torvalds /* 4311da177e4SLinus Torvalds * I have found the disk blocks which were originally used to store 4321da177e4SLinus Torvalds * the FEALIST. now i loop over each contiguous block copying the 4331da177e4SLinus Torvalds * data into the buffer. 4341da177e4SLinus Torvalds */ 4351da177e4SLinus Torvalds for (i = 0; i < nblocks; i += sbi->nbperpage) { 4361da177e4SLinus Torvalds /* 4371da177e4SLinus Torvalds * Determine how many bytes for this request, and round up to 4381da177e4SLinus Torvalds * the nearest aggregate block size 4391da177e4SLinus Torvalds */ 4401da177e4SLinus Torvalds nb = min(PSIZE, nbytes); 4411da177e4SLinus Torvalds bytes_to_read = 4421da177e4SLinus Torvalds ((((nb + sb->s_blocksize - 1)) >> sb->s_blocksize_bits)) 4431da177e4SLinus Torvalds << sb->s_blocksize_bits; 4441da177e4SLinus Torvalds 4451da177e4SLinus Torvalds if (!(mp = read_metapage(ip, blkno + i, bytes_to_read, 1))) 4461da177e4SLinus Torvalds return -EIO; 4471da177e4SLinus Torvalds 4481da177e4SLinus Torvalds memcpy(cp, mp->data, nb); 4491da177e4SLinus Torvalds release_metapage(mp); 4501da177e4SLinus Torvalds 4511da177e4SLinus Torvalds cp += PSIZE; 4521da177e4SLinus Torvalds nbytes -= nb; 4531da177e4SLinus Torvalds } 4541da177e4SLinus Torvalds 4551da177e4SLinus Torvalds return 0; 4561da177e4SLinus Torvalds } 4571da177e4SLinus Torvalds 4581da177e4SLinus Torvalds /* 4591da177e4SLinus Torvalds * NAME: ea_get 4601da177e4SLinus Torvalds * 4611da177e4SLinus Torvalds * FUNCTION: Returns buffer containing existing extended attributes. 4621da177e4SLinus Torvalds * The size of the buffer will be the larger of the existing 4631da177e4SLinus Torvalds * attributes size, or min_size. 4641da177e4SLinus Torvalds * 4651da177e4SLinus Torvalds * The buffer, which may be inlined in the inode or in the 4661da177e4SLinus Torvalds * page cache must be release by calling ea_release or ea_put 4671da177e4SLinus Torvalds * 4681da177e4SLinus Torvalds * PARAMETERS: 4691da177e4SLinus Torvalds * inode - Inode pointer 4701da177e4SLinus Torvalds * ea_buf - Structure to be populated with ealist and its metadata 4711da177e4SLinus Torvalds * min_size- minimum size of buffer to be returned 4721da177e4SLinus Torvalds * 4731da177e4SLinus Torvalds * RETURNS: 0 for success; Other indicates failure 4741da177e4SLinus Torvalds */ 4751da177e4SLinus Torvalds static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size) 4761da177e4SLinus Torvalds { 4771da177e4SLinus Torvalds struct jfs_inode_info *ji = JFS_IP(inode); 4781da177e4SLinus Torvalds struct super_block *sb = inode->i_sb; 4791da177e4SLinus Torvalds int size; 4801da177e4SLinus Torvalds int ea_size = sizeDXD(&ji->ea); 4811da177e4SLinus Torvalds int blocks_needed, current_blocks; 4821da177e4SLinus Torvalds s64 blkno; 4831da177e4SLinus Torvalds int rc; 4841da177e4SLinus Torvalds int quota_allocation = 0; 4851da177e4SLinus Torvalds 4861da177e4SLinus Torvalds /* When fsck.jfs clears a bad ea, it doesn't clear the size */ 4871da177e4SLinus Torvalds if (ji->ea.flag == 0) 4881da177e4SLinus Torvalds ea_size = 0; 4891da177e4SLinus Torvalds 4901da177e4SLinus Torvalds if (ea_size == 0) { 4911da177e4SLinus Torvalds if (min_size == 0) { 4921da177e4SLinus Torvalds ea_buf->flag = 0; 4931da177e4SLinus Torvalds ea_buf->max_size = 0; 4941da177e4SLinus Torvalds ea_buf->xattr = NULL; 4951da177e4SLinus Torvalds return 0; 4961da177e4SLinus Torvalds } 4971da177e4SLinus Torvalds if ((min_size <= sizeof (ji->i_inline_ea)) && 4981da177e4SLinus Torvalds (ji->mode2 & INLINEEA)) { 4991da177e4SLinus Torvalds ea_buf->flag = EA_INLINE | EA_NEW; 5001da177e4SLinus Torvalds ea_buf->max_size = sizeof (ji->i_inline_ea); 5011da177e4SLinus Torvalds ea_buf->xattr = (struct jfs_ea_list *) ji->i_inline_ea; 5021da177e4SLinus Torvalds DXDlength(&ea_buf->new_ea, 0); 5031da177e4SLinus Torvalds DXDaddress(&ea_buf->new_ea, 0); 5041da177e4SLinus Torvalds ea_buf->new_ea.flag = DXD_INLINE; 5051da177e4SLinus Torvalds DXDsize(&ea_buf->new_ea, min_size); 5061da177e4SLinus Torvalds return 0; 5071da177e4SLinus Torvalds } 5081da177e4SLinus Torvalds current_blocks = 0; 5091da177e4SLinus Torvalds } else if (ji->ea.flag & DXD_INLINE) { 5101da177e4SLinus Torvalds if (min_size <= sizeof (ji->i_inline_ea)) { 5111da177e4SLinus Torvalds ea_buf->flag = EA_INLINE; 5121da177e4SLinus Torvalds ea_buf->max_size = sizeof (ji->i_inline_ea); 5131da177e4SLinus Torvalds ea_buf->xattr = (struct jfs_ea_list *) ji->i_inline_ea; 5141da177e4SLinus Torvalds goto size_check; 5151da177e4SLinus Torvalds } 5161da177e4SLinus Torvalds current_blocks = 0; 5171da177e4SLinus Torvalds } else { 5181da177e4SLinus Torvalds if (!(ji->ea.flag & DXD_EXTENT)) { 5191da177e4SLinus Torvalds jfs_error(sb, "ea_get: invalid ea.flag)"); 5201da177e4SLinus Torvalds return -EIO; 5211da177e4SLinus Torvalds } 5221da177e4SLinus Torvalds current_blocks = (ea_size + sb->s_blocksize - 1) >> 5231da177e4SLinus Torvalds sb->s_blocksize_bits; 5241da177e4SLinus Torvalds } 5251da177e4SLinus Torvalds size = max(min_size, ea_size); 5261da177e4SLinus Torvalds 5271da177e4SLinus Torvalds if (size > PSIZE) { 5281da177e4SLinus Torvalds /* 5291da177e4SLinus Torvalds * To keep the rest of the code simple. Allocate a 5301da177e4SLinus Torvalds * contiguous buffer to work with 5311da177e4SLinus Torvalds */ 5321da177e4SLinus Torvalds ea_buf->xattr = kmalloc(size, GFP_KERNEL); 5331da177e4SLinus Torvalds if (ea_buf->xattr == NULL) 5341da177e4SLinus Torvalds return -ENOMEM; 5351da177e4SLinus Torvalds 5361da177e4SLinus Torvalds ea_buf->flag = EA_MALLOC; 5371da177e4SLinus Torvalds ea_buf->max_size = (size + sb->s_blocksize - 1) & 5381da177e4SLinus Torvalds ~(sb->s_blocksize - 1); 5391da177e4SLinus Torvalds 5401da177e4SLinus Torvalds if (ea_size == 0) 5411da177e4SLinus Torvalds return 0; 5421da177e4SLinus Torvalds 5431da177e4SLinus Torvalds if ((rc = ea_read(inode, ea_buf->xattr))) { 5441da177e4SLinus Torvalds kfree(ea_buf->xattr); 5451da177e4SLinus Torvalds ea_buf->xattr = NULL; 5461da177e4SLinus Torvalds return rc; 5471da177e4SLinus Torvalds } 5481da177e4SLinus Torvalds goto size_check; 5491da177e4SLinus Torvalds } 5501da177e4SLinus Torvalds blocks_needed = (min_size + sb->s_blocksize - 1) >> 5511da177e4SLinus Torvalds sb->s_blocksize_bits; 5521da177e4SLinus Torvalds 5531da177e4SLinus Torvalds if (blocks_needed > current_blocks) { 5541da177e4SLinus Torvalds /* Allocate new blocks to quota. */ 5551da177e4SLinus Torvalds if (DQUOT_ALLOC_BLOCK(inode, blocks_needed)) 5561da177e4SLinus Torvalds return -EDQUOT; 5571da177e4SLinus Torvalds 5581da177e4SLinus Torvalds quota_allocation = blocks_needed; 5591da177e4SLinus Torvalds 5601da177e4SLinus Torvalds rc = dbAlloc(inode, INOHINT(inode), (s64) blocks_needed, 5611da177e4SLinus Torvalds &blkno); 5621da177e4SLinus Torvalds if (rc) 5631da177e4SLinus Torvalds goto clean_up; 5641da177e4SLinus Torvalds 5651da177e4SLinus Torvalds DXDlength(&ea_buf->new_ea, blocks_needed); 5661da177e4SLinus Torvalds DXDaddress(&ea_buf->new_ea, blkno); 5671da177e4SLinus Torvalds ea_buf->new_ea.flag = DXD_EXTENT; 5681da177e4SLinus Torvalds DXDsize(&ea_buf->new_ea, min_size); 5691da177e4SLinus Torvalds 5701da177e4SLinus Torvalds ea_buf->flag = EA_EXTENT | EA_NEW; 5711da177e4SLinus Torvalds 5721da177e4SLinus Torvalds ea_buf->mp = get_metapage(inode, blkno, 5731da177e4SLinus Torvalds blocks_needed << sb->s_blocksize_bits, 5741da177e4SLinus Torvalds 1); 5751da177e4SLinus Torvalds if (ea_buf->mp == NULL) { 5761da177e4SLinus Torvalds dbFree(inode, blkno, (s64) blocks_needed); 5771da177e4SLinus Torvalds rc = -EIO; 5781da177e4SLinus Torvalds goto clean_up; 5791da177e4SLinus Torvalds } 5801da177e4SLinus Torvalds ea_buf->xattr = ea_buf->mp->data; 5811da177e4SLinus Torvalds ea_buf->max_size = (min_size + sb->s_blocksize - 1) & 5821da177e4SLinus Torvalds ~(sb->s_blocksize - 1); 5831da177e4SLinus Torvalds if (ea_size == 0) 5841da177e4SLinus Torvalds return 0; 5851da177e4SLinus Torvalds if ((rc = ea_read(inode, ea_buf->xattr))) { 5861da177e4SLinus Torvalds discard_metapage(ea_buf->mp); 5871da177e4SLinus Torvalds dbFree(inode, blkno, (s64) blocks_needed); 5881da177e4SLinus Torvalds goto clean_up; 5891da177e4SLinus Torvalds } 5901da177e4SLinus Torvalds goto size_check; 5911da177e4SLinus Torvalds } 5921da177e4SLinus Torvalds ea_buf->flag = EA_EXTENT; 5931da177e4SLinus Torvalds ea_buf->mp = read_metapage(inode, addressDXD(&ji->ea), 5941da177e4SLinus Torvalds lengthDXD(&ji->ea) << sb->s_blocksize_bits, 5951da177e4SLinus Torvalds 1); 5961da177e4SLinus Torvalds if (ea_buf->mp == NULL) { 5971da177e4SLinus Torvalds rc = -EIO; 5981da177e4SLinus Torvalds goto clean_up; 5991da177e4SLinus Torvalds } 6001da177e4SLinus Torvalds ea_buf->xattr = ea_buf->mp->data; 6011da177e4SLinus Torvalds ea_buf->max_size = (ea_size + sb->s_blocksize - 1) & 6021da177e4SLinus Torvalds ~(sb->s_blocksize - 1); 6031da177e4SLinus Torvalds 6041da177e4SLinus Torvalds size_check: 6051da177e4SLinus Torvalds if (EALIST_SIZE(ea_buf->xattr) != ea_size) { 6061da177e4SLinus Torvalds printk(KERN_ERR "ea_get: invalid extended attribute\n"); 6071da177e4SLinus Torvalds dump_mem("xattr", ea_buf->xattr, ea_size); 6081da177e4SLinus Torvalds ea_release(inode, ea_buf); 6091da177e4SLinus Torvalds rc = -EIO; 6101da177e4SLinus Torvalds goto clean_up; 6111da177e4SLinus Torvalds } 6121da177e4SLinus Torvalds 6131da177e4SLinus Torvalds return ea_size; 6141da177e4SLinus Torvalds 6151da177e4SLinus Torvalds clean_up: 6161da177e4SLinus Torvalds /* Rollback quota allocation */ 6171da177e4SLinus Torvalds if (quota_allocation) 6181da177e4SLinus Torvalds DQUOT_FREE_BLOCK(inode, quota_allocation); 6191da177e4SLinus Torvalds 6201da177e4SLinus Torvalds return (rc); 6211da177e4SLinus Torvalds } 6221da177e4SLinus Torvalds 6231da177e4SLinus Torvalds static void ea_release(struct inode *inode, struct ea_buffer *ea_buf) 6241da177e4SLinus Torvalds { 6251da177e4SLinus Torvalds if (ea_buf->flag & EA_MALLOC) 6261da177e4SLinus Torvalds kfree(ea_buf->xattr); 6271da177e4SLinus Torvalds else if (ea_buf->flag & EA_EXTENT) { 6281da177e4SLinus Torvalds assert(ea_buf->mp); 6291da177e4SLinus Torvalds release_metapage(ea_buf->mp); 6301da177e4SLinus Torvalds 6311da177e4SLinus Torvalds if (ea_buf->flag & EA_NEW) 6321da177e4SLinus Torvalds dbFree(inode, addressDXD(&ea_buf->new_ea), 6331da177e4SLinus Torvalds lengthDXD(&ea_buf->new_ea)); 6341da177e4SLinus Torvalds } 6351da177e4SLinus Torvalds } 6361da177e4SLinus Torvalds 6374f4b401bSDave Kleikamp static int ea_put(tid_t tid, struct inode *inode, struct ea_buffer *ea_buf, 6384f4b401bSDave Kleikamp int new_size) 6391da177e4SLinus Torvalds { 6401da177e4SLinus Torvalds struct jfs_inode_info *ji = JFS_IP(inode); 6411da177e4SLinus Torvalds unsigned long old_blocks, new_blocks; 6421da177e4SLinus Torvalds int rc = 0; 6431da177e4SLinus Torvalds 6441da177e4SLinus Torvalds if (new_size == 0) { 6451da177e4SLinus Torvalds ea_release(inode, ea_buf); 6461da177e4SLinus Torvalds ea_buf = NULL; 6471da177e4SLinus Torvalds } else if (ea_buf->flag & EA_INLINE) { 6481da177e4SLinus Torvalds assert(new_size <= sizeof (ji->i_inline_ea)); 6491da177e4SLinus Torvalds ji->mode2 &= ~INLINEEA; 6501da177e4SLinus Torvalds ea_buf->new_ea.flag = DXD_INLINE; 6511da177e4SLinus Torvalds DXDsize(&ea_buf->new_ea, new_size); 6521da177e4SLinus Torvalds DXDaddress(&ea_buf->new_ea, 0); 6531da177e4SLinus Torvalds DXDlength(&ea_buf->new_ea, 0); 6541da177e4SLinus Torvalds } else if (ea_buf->flag & EA_MALLOC) { 6551da177e4SLinus Torvalds rc = ea_write(inode, ea_buf->xattr, new_size, &ea_buf->new_ea); 6561da177e4SLinus Torvalds kfree(ea_buf->xattr); 6571da177e4SLinus Torvalds } else if (ea_buf->flag & EA_NEW) { 6581da177e4SLinus Torvalds /* We have already allocated a new dxd */ 6591da177e4SLinus Torvalds flush_metapage(ea_buf->mp); 6601da177e4SLinus Torvalds } else { 6611da177e4SLinus Torvalds /* ->xattr must point to original ea's metapage */ 6621da177e4SLinus Torvalds rc = ea_write(inode, ea_buf->xattr, new_size, &ea_buf->new_ea); 6631da177e4SLinus Torvalds discard_metapage(ea_buf->mp); 6641da177e4SLinus Torvalds } 6651da177e4SLinus Torvalds if (rc) 6661da177e4SLinus Torvalds return rc; 6671da177e4SLinus Torvalds 6681da177e4SLinus Torvalds old_blocks = new_blocks = 0; 6691da177e4SLinus Torvalds 6701da177e4SLinus Torvalds if (ji->ea.flag & DXD_EXTENT) { 6711da177e4SLinus Torvalds invalidate_dxd_metapages(inode, ji->ea); 6721da177e4SLinus Torvalds old_blocks = lengthDXD(&ji->ea); 6731da177e4SLinus Torvalds } 6741da177e4SLinus Torvalds 6751da177e4SLinus Torvalds if (ea_buf) { 6761da177e4SLinus Torvalds txEA(tid, inode, &ji->ea, &ea_buf->new_ea); 6771da177e4SLinus Torvalds if (ea_buf->new_ea.flag & DXD_EXTENT) { 6781da177e4SLinus Torvalds new_blocks = lengthDXD(&ea_buf->new_ea); 6791da177e4SLinus Torvalds if (ji->ea.flag & DXD_INLINE) 6801da177e4SLinus Torvalds ji->mode2 |= INLINEEA; 6811da177e4SLinus Torvalds } 6821da177e4SLinus Torvalds ji->ea = ea_buf->new_ea; 6831da177e4SLinus Torvalds } else { 6841da177e4SLinus Torvalds txEA(tid, inode, &ji->ea, NULL); 6851da177e4SLinus Torvalds if (ji->ea.flag & DXD_INLINE) 6861da177e4SLinus Torvalds ji->mode2 |= INLINEEA; 6871da177e4SLinus Torvalds ji->ea.flag = 0; 6881da177e4SLinus Torvalds ji->ea.size = 0; 6891da177e4SLinus Torvalds } 6901da177e4SLinus Torvalds 6911da177e4SLinus Torvalds /* If old blocks exist, they must be removed from quota allocation. */ 6921da177e4SLinus Torvalds if (old_blocks) 6931da177e4SLinus Torvalds DQUOT_FREE_BLOCK(inode, old_blocks); 6941da177e4SLinus Torvalds 6951da177e4SLinus Torvalds inode->i_ctime = CURRENT_TIME; 6961da177e4SLinus Torvalds 6974f4b401bSDave Kleikamp return 0; 6981da177e4SLinus Torvalds } 6991da177e4SLinus Torvalds 7001da177e4SLinus Torvalds /* 7011da177e4SLinus Torvalds * can_set_system_xattr 7021da177e4SLinus Torvalds * 7031da177e4SLinus Torvalds * This code is specific to the system.* namespace. It contains policy 7041da177e4SLinus Torvalds * which doesn't belong in the main xattr codepath. 7051da177e4SLinus Torvalds */ 7061da177e4SLinus Torvalds static int can_set_system_xattr(struct inode *inode, const char *name, 7071da177e4SLinus Torvalds const void *value, size_t value_len) 7081da177e4SLinus Torvalds { 7091da177e4SLinus Torvalds #ifdef CONFIG_JFS_POSIX_ACL 7101da177e4SLinus Torvalds struct posix_acl *acl; 7111da177e4SLinus Torvalds int rc; 7121da177e4SLinus Torvalds 7131da177e4SLinus Torvalds if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) 7141da177e4SLinus Torvalds return -EPERM; 7151da177e4SLinus Torvalds 7161da177e4SLinus Torvalds /* 7179a59f452SChristoph Hellwig * POSIX_ACL_XATTR_ACCESS is tied to i_mode 7181da177e4SLinus Torvalds */ 7199a59f452SChristoph Hellwig if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0) { 7201da177e4SLinus Torvalds acl = posix_acl_from_xattr(value, value_len); 7211da177e4SLinus Torvalds if (IS_ERR(acl)) { 7221da177e4SLinus Torvalds rc = PTR_ERR(acl); 7231da177e4SLinus Torvalds printk(KERN_ERR "posix_acl_from_xattr returned %d\n", 7241da177e4SLinus Torvalds rc); 7251da177e4SLinus Torvalds return rc; 7261da177e4SLinus Torvalds } 7271da177e4SLinus Torvalds if (acl) { 7281da177e4SLinus Torvalds mode_t mode = inode->i_mode; 7291da177e4SLinus Torvalds rc = posix_acl_equiv_mode(acl, &mode); 7301da177e4SLinus Torvalds posix_acl_release(acl); 7311da177e4SLinus Torvalds if (rc < 0) { 7321da177e4SLinus Torvalds printk(KERN_ERR 7331da177e4SLinus Torvalds "posix_acl_equiv_mode returned %d\n", 7341da177e4SLinus Torvalds rc); 7351da177e4SLinus Torvalds return rc; 7361da177e4SLinus Torvalds } 7371da177e4SLinus Torvalds inode->i_mode = mode; 7381da177e4SLinus Torvalds mark_inode_dirty(inode); 7391da177e4SLinus Torvalds } 7401da177e4SLinus Torvalds /* 7411da177e4SLinus Torvalds * We're changing the ACL. Get rid of the cached one 7421da177e4SLinus Torvalds */ 7431da177e4SLinus Torvalds acl =JFS_IP(inode)->i_acl; 7441da177e4SLinus Torvalds if (acl != JFS_ACL_NOT_CACHED) 7451da177e4SLinus Torvalds posix_acl_release(acl); 7461da177e4SLinus Torvalds JFS_IP(inode)->i_acl = JFS_ACL_NOT_CACHED; 7471da177e4SLinus Torvalds 7481da177e4SLinus Torvalds return 0; 7499a59f452SChristoph Hellwig } else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0) { 7501da177e4SLinus Torvalds acl = posix_acl_from_xattr(value, value_len); 7511da177e4SLinus Torvalds if (IS_ERR(acl)) { 7521da177e4SLinus Torvalds rc = PTR_ERR(acl); 7531da177e4SLinus Torvalds printk(KERN_ERR "posix_acl_from_xattr returned %d\n", 7541da177e4SLinus Torvalds rc); 7551da177e4SLinus Torvalds return rc; 7561da177e4SLinus Torvalds } 7571da177e4SLinus Torvalds posix_acl_release(acl); 7581da177e4SLinus Torvalds 7591da177e4SLinus Torvalds /* 7601da177e4SLinus Torvalds * We're changing the default ACL. Get rid of the cached one 7611da177e4SLinus Torvalds */ 7621da177e4SLinus Torvalds acl =JFS_IP(inode)->i_default_acl; 7631da177e4SLinus Torvalds if (acl && (acl != JFS_ACL_NOT_CACHED)) 7641da177e4SLinus Torvalds posix_acl_release(acl); 7651da177e4SLinus Torvalds JFS_IP(inode)->i_default_acl = JFS_ACL_NOT_CACHED; 7661da177e4SLinus Torvalds 7671da177e4SLinus Torvalds return 0; 7681da177e4SLinus Torvalds } 7691da177e4SLinus Torvalds #endif /* CONFIG_JFS_POSIX_ACL */ 7701da177e4SLinus Torvalds return -EOPNOTSUPP; 7711da177e4SLinus Torvalds } 7721da177e4SLinus Torvalds 7731da177e4SLinus Torvalds static int can_set_xattr(struct inode *inode, const char *name, 7741da177e4SLinus Torvalds const void *value, size_t value_len) 7751da177e4SLinus Torvalds { 7761da177e4SLinus Torvalds if (IS_RDONLY(inode)) 7771da177e4SLinus Torvalds return -EROFS; 7781da177e4SLinus Torvalds 7796211502dSDave Kleikamp if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) 7801da177e4SLinus Torvalds return -EPERM; 7811da177e4SLinus Torvalds 7821da177e4SLinus Torvalds if(strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) == 0) 7831da177e4SLinus Torvalds /* 7841da177e4SLinus Torvalds * "system.*" 7851da177e4SLinus Torvalds */ 7861da177e4SLinus Torvalds return can_set_system_xattr(inode, name, value, value_len); 7871da177e4SLinus Torvalds 78859192ed9SIan Dall if(strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) 7891da177e4SLinus Torvalds return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM); 7901da177e4SLinus Torvalds 7911da177e4SLinus Torvalds #ifdef CONFIG_JFS_SECURITY 7921da177e4SLinus Torvalds if (strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) 79359192ed9SIan Dall == 0) 7941da177e4SLinus Torvalds return 0; /* Leave it to the security module */ 7951da177e4SLinus Torvalds #endif 7961da177e4SLinus Torvalds 7971da177e4SLinus Torvalds if((strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) != 0) && 7981da177e4SLinus Torvalds (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) != 0)) 7991da177e4SLinus Torvalds return -EOPNOTSUPP; 8001da177e4SLinus Torvalds 8011da177e4SLinus Torvalds if (!S_ISREG(inode->i_mode) && 8021da177e4SLinus Torvalds (!S_ISDIR(inode->i_mode) || inode->i_mode &S_ISVTX)) 8031da177e4SLinus Torvalds return -EPERM; 8041da177e4SLinus Torvalds 8051da177e4SLinus Torvalds return permission(inode, MAY_WRITE, NULL); 8061da177e4SLinus Torvalds } 8071da177e4SLinus Torvalds 8084f4b401bSDave Kleikamp int __jfs_setxattr(tid_t tid, struct inode *inode, const char *name, 8094f4b401bSDave Kleikamp const void *value, size_t value_len, int flags) 8101da177e4SLinus Torvalds { 8111da177e4SLinus Torvalds struct jfs_ea_list *ealist; 8121da177e4SLinus Torvalds struct jfs_ea *ea, *old_ea = NULL, *next_ea = NULL; 8131da177e4SLinus Torvalds struct ea_buffer ea_buf; 8141da177e4SLinus Torvalds int old_ea_size = 0; 8151da177e4SLinus Torvalds int xattr_size; 8161da177e4SLinus Torvalds int new_size; 8171da177e4SLinus Torvalds int namelen = strlen(name); 8181da177e4SLinus Torvalds char *os2name = NULL; 8191da177e4SLinus Torvalds int found = 0; 8201da177e4SLinus Torvalds int rc; 8211da177e4SLinus Torvalds int length; 8221da177e4SLinus Torvalds 8231da177e4SLinus Torvalds if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { 8241da177e4SLinus Torvalds os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1, 8251da177e4SLinus Torvalds GFP_KERNEL); 8261da177e4SLinus Torvalds if (!os2name) 8271da177e4SLinus Torvalds return -ENOMEM; 8281da177e4SLinus Torvalds strcpy(os2name, name + XATTR_OS2_PREFIX_LEN); 8291da177e4SLinus Torvalds name = os2name; 8301da177e4SLinus Torvalds namelen -= XATTR_OS2_PREFIX_LEN; 8311da177e4SLinus Torvalds } 8321da177e4SLinus Torvalds 8331da177e4SLinus Torvalds down_write(&JFS_IP(inode)->xattr_sem); 8341da177e4SLinus Torvalds 8351da177e4SLinus Torvalds xattr_size = ea_get(inode, &ea_buf, 0); 8361da177e4SLinus Torvalds if (xattr_size < 0) { 8371da177e4SLinus Torvalds rc = xattr_size; 8381da177e4SLinus Torvalds goto out; 8391da177e4SLinus Torvalds } 8401da177e4SLinus Torvalds 8411da177e4SLinus Torvalds again: 8421da177e4SLinus Torvalds ealist = (struct jfs_ea_list *) ea_buf.xattr; 8431da177e4SLinus Torvalds new_size = sizeof (struct jfs_ea_list); 8441da177e4SLinus Torvalds 8451da177e4SLinus Torvalds if (xattr_size) { 8461da177e4SLinus Torvalds for (ea = FIRST_EA(ealist); ea < END_EALIST(ealist); 8471da177e4SLinus Torvalds ea = NEXT_EA(ea)) { 8481da177e4SLinus Torvalds if ((namelen == ea->namelen) && 8491da177e4SLinus Torvalds (memcmp(name, ea->name, namelen) == 0)) { 8501da177e4SLinus Torvalds found = 1; 8511da177e4SLinus Torvalds if (flags & XATTR_CREATE) { 8521da177e4SLinus Torvalds rc = -EEXIST; 8531da177e4SLinus Torvalds goto release; 8541da177e4SLinus Torvalds } 8551da177e4SLinus Torvalds old_ea = ea; 8561da177e4SLinus Torvalds old_ea_size = EA_SIZE(ea); 8571da177e4SLinus Torvalds next_ea = NEXT_EA(ea); 8581da177e4SLinus Torvalds } else 8591da177e4SLinus Torvalds new_size += EA_SIZE(ea); 8601da177e4SLinus Torvalds } 8611da177e4SLinus Torvalds } 8621da177e4SLinus Torvalds 8631da177e4SLinus Torvalds if (!found) { 8641da177e4SLinus Torvalds if (flags & XATTR_REPLACE) { 8651da177e4SLinus Torvalds rc = -ENODATA; 8661da177e4SLinus Torvalds goto release; 8671da177e4SLinus Torvalds } 8681da177e4SLinus Torvalds if (value == NULL) { 8691da177e4SLinus Torvalds rc = 0; 8701da177e4SLinus Torvalds goto release; 8711da177e4SLinus Torvalds } 8721da177e4SLinus Torvalds } 8731da177e4SLinus Torvalds if (value) 8741da177e4SLinus Torvalds new_size += sizeof (struct jfs_ea) + namelen + 1 + value_len; 8751da177e4SLinus Torvalds 8761da177e4SLinus Torvalds if (new_size > ea_buf.max_size) { 8771da177e4SLinus Torvalds /* 8781da177e4SLinus Torvalds * We need to allocate more space for merged ea list. 8791da177e4SLinus Torvalds * We should only have loop to again: once. 8801da177e4SLinus Torvalds */ 8811da177e4SLinus Torvalds ea_release(inode, &ea_buf); 8821da177e4SLinus Torvalds xattr_size = ea_get(inode, &ea_buf, new_size); 8831da177e4SLinus Torvalds if (xattr_size < 0) { 8841da177e4SLinus Torvalds rc = xattr_size; 8851da177e4SLinus Torvalds goto out; 8861da177e4SLinus Torvalds } 8871da177e4SLinus Torvalds goto again; 8881da177e4SLinus Torvalds } 8891da177e4SLinus Torvalds 8901da177e4SLinus Torvalds /* Remove old ea of the same name */ 8911da177e4SLinus Torvalds if (found) { 8921da177e4SLinus Torvalds /* number of bytes following target EA */ 8931da177e4SLinus Torvalds length = (char *) END_EALIST(ealist) - (char *) next_ea; 8941da177e4SLinus Torvalds if (length > 0) 8951da177e4SLinus Torvalds memmove(old_ea, next_ea, length); 8961da177e4SLinus Torvalds xattr_size -= old_ea_size; 8971da177e4SLinus Torvalds } 8981da177e4SLinus Torvalds 8991da177e4SLinus Torvalds /* Add new entry to the end */ 9001da177e4SLinus Torvalds if (value) { 9011da177e4SLinus Torvalds if (xattr_size == 0) 9021da177e4SLinus Torvalds /* Completely new ea list */ 9031da177e4SLinus Torvalds xattr_size = sizeof (struct jfs_ea_list); 9041da177e4SLinus Torvalds 9051da177e4SLinus Torvalds ea = (struct jfs_ea *) ((char *) ealist + xattr_size); 9061da177e4SLinus Torvalds ea->flag = 0; 9071da177e4SLinus Torvalds ea->namelen = namelen; 9081da177e4SLinus Torvalds ea->valuelen = (cpu_to_le16(value_len)); 9091da177e4SLinus Torvalds memcpy(ea->name, name, namelen); 9101da177e4SLinus Torvalds ea->name[namelen] = 0; 9111da177e4SLinus Torvalds if (value_len) 9121da177e4SLinus Torvalds memcpy(&ea->name[namelen + 1], value, value_len); 9131da177e4SLinus Torvalds xattr_size += EA_SIZE(ea); 9141da177e4SLinus Torvalds } 9151da177e4SLinus Torvalds 9161da177e4SLinus Torvalds /* DEBUG - If we did this right, these number match */ 9171da177e4SLinus Torvalds if (xattr_size != new_size) { 9181da177e4SLinus Torvalds printk(KERN_ERR 9191da177e4SLinus Torvalds "jfs_xsetattr: xattr_size = %d, new_size = %d\n", 9201da177e4SLinus Torvalds xattr_size, new_size); 9211da177e4SLinus Torvalds 9221da177e4SLinus Torvalds rc = -EINVAL; 9231da177e4SLinus Torvalds goto release; 9241da177e4SLinus Torvalds } 9251da177e4SLinus Torvalds 9261da177e4SLinus Torvalds /* 9271da177e4SLinus Torvalds * If we're left with an empty list, there's no ea 9281da177e4SLinus Torvalds */ 9291da177e4SLinus Torvalds if (new_size == sizeof (struct jfs_ea_list)) 9301da177e4SLinus Torvalds new_size = 0; 9311da177e4SLinus Torvalds 9321da177e4SLinus Torvalds ealist->size = cpu_to_le32(new_size); 9331da177e4SLinus Torvalds 9344f4b401bSDave Kleikamp rc = ea_put(tid, inode, &ea_buf, new_size); 9351da177e4SLinus Torvalds 9361da177e4SLinus Torvalds goto out; 9371da177e4SLinus Torvalds release: 9381da177e4SLinus Torvalds ea_release(inode, &ea_buf); 9391da177e4SLinus Torvalds out: 9401da177e4SLinus Torvalds up_write(&JFS_IP(inode)->xattr_sem); 9411da177e4SLinus Torvalds 9421da177e4SLinus Torvalds kfree(os2name); 9431da177e4SLinus Torvalds 9441da177e4SLinus Torvalds return rc; 9451da177e4SLinus Torvalds } 9461da177e4SLinus Torvalds 9471da177e4SLinus Torvalds int jfs_setxattr(struct dentry *dentry, const char *name, const void *value, 9481da177e4SLinus Torvalds size_t value_len, int flags) 9491da177e4SLinus Torvalds { 9504f4b401bSDave Kleikamp struct inode *inode = dentry->d_inode; 9514f4b401bSDave Kleikamp struct jfs_inode_info *ji = JFS_IP(inode); 9524f4b401bSDave Kleikamp int rc; 9534f4b401bSDave Kleikamp tid_t tid; 9544f4b401bSDave Kleikamp 9554f4b401bSDave Kleikamp if ((rc = can_set_xattr(inode, name, value, value_len))) 9564f4b401bSDave Kleikamp return rc; 9574f4b401bSDave Kleikamp 9581da177e4SLinus Torvalds if (value == NULL) { /* empty EA, do not remove */ 9591da177e4SLinus Torvalds value = ""; 9601da177e4SLinus Torvalds value_len = 0; 9611da177e4SLinus Torvalds } 9621da177e4SLinus Torvalds 9634f4b401bSDave Kleikamp tid = txBegin(inode->i_sb, 0); 9644f4b401bSDave Kleikamp down(&ji->commit_sem); 9654f4b401bSDave Kleikamp rc = __jfs_setxattr(tid, dentry->d_inode, name, value, value_len, 9664f4b401bSDave Kleikamp flags); 9674f4b401bSDave Kleikamp if (!rc) 9684f4b401bSDave Kleikamp rc = txCommit(tid, 1, &inode, 0); 9694f4b401bSDave Kleikamp txEnd(tid); 9704f4b401bSDave Kleikamp up(&ji->commit_sem); 9714f4b401bSDave Kleikamp 9724f4b401bSDave Kleikamp return rc; 9731da177e4SLinus Torvalds } 9741da177e4SLinus Torvalds 9751da177e4SLinus Torvalds static int can_get_xattr(struct inode *inode, const char *name) 9761da177e4SLinus Torvalds { 9771da177e4SLinus Torvalds #ifdef CONFIG_JFS_SECURITY 9781da177e4SLinus Torvalds if(strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) 9791da177e4SLinus Torvalds return 0; 9801da177e4SLinus Torvalds #endif 9811da177e4SLinus Torvalds 9821da177e4SLinus Torvalds if(strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) 9831da177e4SLinus Torvalds return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM); 9841da177e4SLinus Torvalds 9851da177e4SLinus Torvalds if(strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) == 0) 9861da177e4SLinus Torvalds return 0; 9871da177e4SLinus Torvalds 9881da177e4SLinus Torvalds return permission(inode, MAY_READ, NULL); 9891da177e4SLinus Torvalds } 9901da177e4SLinus Torvalds 9911da177e4SLinus Torvalds ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data, 9921da177e4SLinus Torvalds size_t buf_size) 9931da177e4SLinus Torvalds { 9941da177e4SLinus Torvalds struct jfs_ea_list *ealist; 9951da177e4SLinus Torvalds struct jfs_ea *ea; 9961da177e4SLinus Torvalds struct ea_buffer ea_buf; 9971da177e4SLinus Torvalds int xattr_size; 9981da177e4SLinus Torvalds ssize_t size; 9991da177e4SLinus Torvalds int namelen = strlen(name); 10001da177e4SLinus Torvalds char *os2name = NULL; 10011da177e4SLinus Torvalds int rc; 10021da177e4SLinus Torvalds char *value; 10031da177e4SLinus Torvalds 10041da177e4SLinus Torvalds if ((rc = can_get_xattr(inode, name))) 10051da177e4SLinus Torvalds return rc; 10061da177e4SLinus Torvalds 10071da177e4SLinus Torvalds if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { 10081da177e4SLinus Torvalds os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1, 10091da177e4SLinus Torvalds GFP_KERNEL); 10101da177e4SLinus Torvalds if (!os2name) 10111da177e4SLinus Torvalds return -ENOMEM; 10121da177e4SLinus Torvalds strcpy(os2name, name + XATTR_OS2_PREFIX_LEN); 10131da177e4SLinus Torvalds name = os2name; 10141da177e4SLinus Torvalds namelen -= XATTR_OS2_PREFIX_LEN; 10151da177e4SLinus Torvalds } 10161da177e4SLinus Torvalds 10171da177e4SLinus Torvalds down_read(&JFS_IP(inode)->xattr_sem); 10181da177e4SLinus Torvalds 10191da177e4SLinus Torvalds xattr_size = ea_get(inode, &ea_buf, 0); 10201da177e4SLinus Torvalds 10211da177e4SLinus Torvalds if (xattr_size < 0) { 10221da177e4SLinus Torvalds size = xattr_size; 10231da177e4SLinus Torvalds goto out; 10241da177e4SLinus Torvalds } 10251da177e4SLinus Torvalds 10261da177e4SLinus Torvalds if (xattr_size == 0) 10271da177e4SLinus Torvalds goto not_found; 10281da177e4SLinus Torvalds 10291da177e4SLinus Torvalds ealist = (struct jfs_ea_list *) ea_buf.xattr; 10301da177e4SLinus Torvalds 10311da177e4SLinus Torvalds /* Find the named attribute */ 10321da177e4SLinus Torvalds for (ea = FIRST_EA(ealist); ea < END_EALIST(ealist); ea = NEXT_EA(ea)) 10331da177e4SLinus Torvalds if ((namelen == ea->namelen) && 10341da177e4SLinus Torvalds memcmp(name, ea->name, namelen) == 0) { 10351da177e4SLinus Torvalds /* Found it */ 10361da177e4SLinus Torvalds size = le16_to_cpu(ea->valuelen); 10371da177e4SLinus Torvalds if (!data) 10381da177e4SLinus Torvalds goto release; 10391da177e4SLinus Torvalds else if (size > buf_size) { 10401da177e4SLinus Torvalds size = -ERANGE; 10411da177e4SLinus Torvalds goto release; 10421da177e4SLinus Torvalds } 10431da177e4SLinus Torvalds value = ((char *) &ea->name) + ea->namelen + 1; 10441da177e4SLinus Torvalds memcpy(data, value, size); 10451da177e4SLinus Torvalds goto release; 10461da177e4SLinus Torvalds } 10471da177e4SLinus Torvalds not_found: 10481da177e4SLinus Torvalds size = -ENODATA; 10491da177e4SLinus Torvalds release: 10501da177e4SLinus Torvalds ea_release(inode, &ea_buf); 10511da177e4SLinus Torvalds out: 10521da177e4SLinus Torvalds up_read(&JFS_IP(inode)->xattr_sem); 10531da177e4SLinus Torvalds 10541da177e4SLinus Torvalds kfree(os2name); 10551da177e4SLinus Torvalds 10561da177e4SLinus Torvalds return size; 10571da177e4SLinus Torvalds } 10581da177e4SLinus Torvalds 10591da177e4SLinus Torvalds ssize_t jfs_getxattr(struct dentry *dentry, const char *name, void *data, 10601da177e4SLinus Torvalds size_t buf_size) 10611da177e4SLinus Torvalds { 10621da177e4SLinus Torvalds int err; 10631da177e4SLinus Torvalds 10641da177e4SLinus Torvalds err = __jfs_getxattr(dentry->d_inode, name, data, buf_size); 10651da177e4SLinus Torvalds 10661da177e4SLinus Torvalds return err; 10671da177e4SLinus Torvalds } 10681da177e4SLinus Torvalds 10691da177e4SLinus Torvalds /* 10701da177e4SLinus Torvalds * No special permissions are needed to list attributes except for trusted.* 10711da177e4SLinus Torvalds */ 10721da177e4SLinus Torvalds static inline int can_list(struct jfs_ea *ea) 10731da177e4SLinus Torvalds { 10741da177e4SLinus Torvalds return (strncmp(ea->name, XATTR_TRUSTED_PREFIX, 10751da177e4SLinus Torvalds XATTR_TRUSTED_PREFIX_LEN) || 10761da177e4SLinus Torvalds capable(CAP_SYS_ADMIN)); 10771da177e4SLinus Torvalds } 10781da177e4SLinus Torvalds 10791da177e4SLinus Torvalds ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size) 10801da177e4SLinus Torvalds { 10811da177e4SLinus Torvalds struct inode *inode = dentry->d_inode; 10821da177e4SLinus Torvalds char *buffer; 10831da177e4SLinus Torvalds ssize_t size = 0; 10841da177e4SLinus Torvalds int xattr_size; 10851da177e4SLinus Torvalds struct jfs_ea_list *ealist; 10861da177e4SLinus Torvalds struct jfs_ea *ea; 10871da177e4SLinus Torvalds struct ea_buffer ea_buf; 10881da177e4SLinus Torvalds 10891da177e4SLinus Torvalds down_read(&JFS_IP(inode)->xattr_sem); 10901da177e4SLinus Torvalds 10911da177e4SLinus Torvalds xattr_size = ea_get(inode, &ea_buf, 0); 10921da177e4SLinus Torvalds if (xattr_size < 0) { 10931da177e4SLinus Torvalds size = xattr_size; 10941da177e4SLinus Torvalds goto out; 10951da177e4SLinus Torvalds } 10961da177e4SLinus Torvalds 10971da177e4SLinus Torvalds if (xattr_size == 0) 10981da177e4SLinus Torvalds goto release; 10991da177e4SLinus Torvalds 11001da177e4SLinus Torvalds ealist = (struct jfs_ea_list *) ea_buf.xattr; 11011da177e4SLinus Torvalds 11021da177e4SLinus Torvalds /* compute required size of list */ 11031da177e4SLinus Torvalds for (ea = FIRST_EA(ealist); ea < END_EALIST(ealist); ea = NEXT_EA(ea)) { 11041da177e4SLinus Torvalds if (can_list(ea)) 11051da177e4SLinus Torvalds size += name_size(ea) + 1; 11061da177e4SLinus Torvalds } 11071da177e4SLinus Torvalds 11081da177e4SLinus Torvalds if (!data) 11091da177e4SLinus Torvalds goto release; 11101da177e4SLinus Torvalds 11111da177e4SLinus Torvalds if (size > buf_size) { 11121da177e4SLinus Torvalds size = -ERANGE; 11131da177e4SLinus Torvalds goto release; 11141da177e4SLinus Torvalds } 11151da177e4SLinus Torvalds 11161da177e4SLinus Torvalds /* Copy attribute names to buffer */ 11171da177e4SLinus Torvalds buffer = data; 11181da177e4SLinus Torvalds for (ea = FIRST_EA(ealist); ea < END_EALIST(ealist); ea = NEXT_EA(ea)) { 11191da177e4SLinus Torvalds if (can_list(ea)) { 11201da177e4SLinus Torvalds int namelen = copy_name(buffer, ea); 11211da177e4SLinus Torvalds buffer += namelen + 1; 11221da177e4SLinus Torvalds } 11231da177e4SLinus Torvalds } 11241da177e4SLinus Torvalds 11251da177e4SLinus Torvalds release: 11261da177e4SLinus Torvalds ea_release(inode, &ea_buf); 11271da177e4SLinus Torvalds out: 11281da177e4SLinus Torvalds up_read(&JFS_IP(inode)->xattr_sem); 11291da177e4SLinus Torvalds return size; 11301da177e4SLinus Torvalds } 11311da177e4SLinus Torvalds 11321da177e4SLinus Torvalds int jfs_removexattr(struct dentry *dentry, const char *name) 11331da177e4SLinus Torvalds { 11344f4b401bSDave Kleikamp struct inode *inode = dentry->d_inode; 11354f4b401bSDave Kleikamp struct jfs_inode_info *ji = JFS_IP(inode); 11364f4b401bSDave Kleikamp int rc; 11374f4b401bSDave Kleikamp tid_t tid; 11384f4b401bSDave Kleikamp 11394f4b401bSDave Kleikamp if ((rc = can_set_xattr(inode, name, NULL, 0))) 11404f4b401bSDave Kleikamp return rc; 11414f4b401bSDave Kleikamp 11424f4b401bSDave Kleikamp tid = txBegin(inode->i_sb, 0); 11434f4b401bSDave Kleikamp down(&ji->commit_sem); 11444f4b401bSDave Kleikamp rc = __jfs_setxattr(tid, dentry->d_inode, name, NULL, 0, XATTR_REPLACE); 11454f4b401bSDave Kleikamp if (!rc) 11464f4b401bSDave Kleikamp rc = txCommit(tid, 1, &inode, 0); 11474f4b401bSDave Kleikamp txEnd(tid); 11484f4b401bSDave Kleikamp up(&ji->commit_sem); 11494f4b401bSDave Kleikamp 11504f4b401bSDave Kleikamp return rc; 11511da177e4SLinus Torvalds } 11521d15b10fSDave Kleikamp 11531d15b10fSDave Kleikamp #ifdef CONFIG_JFS_SECURITY 11541d15b10fSDave Kleikamp int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir) 11551d15b10fSDave Kleikamp { 11561d15b10fSDave Kleikamp int rc; 11571d15b10fSDave Kleikamp size_t len; 11581d15b10fSDave Kleikamp void *value; 11591d15b10fSDave Kleikamp char *suffix; 11601d15b10fSDave Kleikamp char *name; 11611d15b10fSDave Kleikamp 11621d15b10fSDave Kleikamp rc = security_inode_init_security(inode, dir, &suffix, &value, &len); 11631d15b10fSDave Kleikamp if (rc) { 11641d15b10fSDave Kleikamp if (rc == -EOPNOTSUPP) 11651d15b10fSDave Kleikamp return 0; 11661d15b10fSDave Kleikamp return rc; 11671d15b10fSDave Kleikamp } 11681d15b10fSDave Kleikamp name = kmalloc(XATTR_SECURITY_PREFIX_LEN + 1 + strlen(suffix), 11691d15b10fSDave Kleikamp GFP_NOFS); 11701d15b10fSDave Kleikamp if (!name) { 11711d15b10fSDave Kleikamp rc = -ENOMEM; 11721d15b10fSDave Kleikamp goto kmalloc_failed; 11731d15b10fSDave Kleikamp } 11741d15b10fSDave Kleikamp strcpy(name, XATTR_SECURITY_PREFIX); 11751d15b10fSDave Kleikamp strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix); 11761d15b10fSDave Kleikamp 11771d15b10fSDave Kleikamp rc = __jfs_setxattr(tid, inode, name, value, len, 0); 11781d15b10fSDave Kleikamp 11791d15b10fSDave Kleikamp kfree(name); 11801d15b10fSDave Kleikamp kmalloc_failed: 11811d15b10fSDave Kleikamp kfree(suffix); 11821d15b10fSDave Kleikamp kfree(value); 11831d15b10fSDave Kleikamp 11841d15b10fSDave Kleikamp return rc; 11851d15b10fSDave Kleikamp } 11861d15b10fSDave Kleikamp #endif 1187