⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xattr.c

📁 jfs-2.4-1.1.7.tar.gz jfs 2.4-1.1.7 源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	} else if (ji->ea.flag & DXD_INLINE) {		if (min_size <= sizeof (ji->i_inline_ea)) {			ea_buf->flag = EA_INLINE;			ea_buf->max_size = sizeof (ji->i_inline_ea);			ea_buf->xattr = (struct jfs_ea_list *) ji->i_inline_ea;			goto size_check;		}		current_blocks = 0;	} else {		if (!(ji->ea.flag & DXD_EXTENT)) {			jfs_error(sb, "ea_get: invalid ea.flag)");			return -EIO;		}		current_blocks = (ea_size + sb->s_blocksize - 1) >>		    sb->s_blocksize_bits;	}	size = max(min_size, ea_size);	if (size > PSIZE) {		/*		 * To keep the rest of the code simple.  Allocate a		 * contiguous buffer to work with		 */		ea_buf->xattr = kmalloc(size, GFP_KERNEL);		if (ea_buf->xattr == NULL)			return -ENOMEM;		ea_buf->flag = EA_MALLOC;		ea_buf->max_size = (size + sb->s_blocksize - 1) &		    ~(sb->s_blocksize - 1);		if (ea_size == 0)			return 0;		if ((rc = ea_read(inode, ea_buf->xattr))) {			kfree(ea_buf->xattr);			ea_buf->xattr = NULL;			return rc;		}		goto size_check;	}	blocks_needed = (min_size + sb->s_blocksize - 1) >>	    sb->s_blocksize_bits;	if (blocks_needed > current_blocks) {		rc = dbAlloc(inode, INOHINT(inode), (s64) blocks_needed,			     &blkno);		if (rc)			return rc;		DXDlength(&ea_buf->new_ea, blocks_needed);		DXDaddress(&ea_buf->new_ea, blkno);		ea_buf->new_ea.flag = DXD_EXTENT;		DXDsize(&ea_buf->new_ea, min_size);		ea_buf->flag = EA_EXTENT | EA_NEW;		ea_buf->mp = get_metapage(inode, blkno,					  blocks_needed << sb->s_blocksize_bits,					  1);		if (ea_buf->mp == NULL) {			dbFree(inode, blkno, (s64) blocks_needed);			return -EIO;		}		ea_buf->xattr = ea_buf->mp->data;		ea_buf->max_size = (min_size + sb->s_blocksize - 1) &		    ~(sb->s_blocksize - 1);		if (ea_size == 0)			return 0;		if ((rc = ea_read(inode, ea_buf->xattr))) {			discard_metapage(ea_buf->mp);			dbFree(inode, blkno, (s64) blocks_needed);			return rc;		}		goto size_check;	}	ea_buf->flag = EA_EXTENT;	ea_buf->mp = read_metapage(inode, addressDXD(&ji->ea),				   lengthDXD(&ji->ea) << sb->s_blocksize_bits,				   1);	if (ea_buf->mp == NULL)		return -EIO;	ea_buf->xattr = ea_buf->mp->data;	ea_buf->max_size = (ea_size + sb->s_blocksize - 1) &	    ~(sb->s_blocksize - 1);      size_check:	if (EALIST_SIZE(ea_buf->xattr) != ea_size) {		printk(KERN_ERR "ea_get: invalid extended attribute\n");		dump_mem("xattr", ea_buf->xattr, ea_size);		ea_release(inode, ea_buf);		return -EIO;	}	return ea_size;}static void ea_release(struct inode *inode, struct ea_buffer *ea_buf){	if (ea_buf->flag & EA_MALLOC)		kfree(ea_buf->xattr);	else if (ea_buf->flag & EA_EXTENT) {		assert(ea_buf->mp);		release_metapage(ea_buf->mp);		if (ea_buf->flag & EA_NEW)			dbFree(inode, addressDXD(&ea_buf->new_ea),			       lengthDXD(&ea_buf->new_ea));	}}static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size){	struct jfs_inode_info *ji = JFS_IP(inode);	unsigned long old_blocks, new_blocks;	int rc = 0;	tid_t tid;	if (new_size == 0) {		ea_release(inode, ea_buf);		ea_buf = 0;	} else if (ea_buf->flag & EA_INLINE) {		assert(new_size <= sizeof (ji->i_inline_ea));		ji->mode2 &= ~INLINEEA;		ea_buf->new_ea.flag = DXD_INLINE;		DXDsize(&ea_buf->new_ea, new_size);		DXDaddress(&ea_buf->new_ea, 0);		DXDlength(&ea_buf->new_ea, 0);	} else if (ea_buf->flag & EA_MALLOC) {		rc = ea_write(inode, ea_buf->xattr, new_size, &ea_buf->new_ea);		kfree(ea_buf->xattr);	} else if (ea_buf->flag & EA_NEW) {		/* We have already allocated a new dxd */		flush_metapage(ea_buf->mp);	} else {		/* ->xattr must point to original ea's metapage */		rc = ea_write(inode, ea_buf->xattr, new_size, &ea_buf->new_ea);		discard_metapage(ea_buf->mp);	}	if (rc)		return rc;	tid = txBegin(inode->i_sb, 0);	down(&ji->commit_sem);	old_blocks = new_blocks = 0;	if (ji->ea.flag & DXD_EXTENT) {		invalidate_dxd_metapages(inode, ji->ea);		old_blocks = lengthDXD(&ji->ea);	}	if (ea_buf) {		txEA(tid, inode, &ji->ea, &ea_buf->new_ea);		if (ea_buf->new_ea.flag & DXD_EXTENT) {			new_blocks = lengthDXD(&ea_buf->new_ea);			if (ji->ea.flag & DXD_INLINE)				ji->mode2 |= INLINEEA;		}		ji->ea = ea_buf->new_ea;	} else {		txEA(tid, inode, &ji->ea, 0);		if (ji->ea.flag & DXD_INLINE)			ji->mode2 |= INLINEEA;		ji->ea.flag = 0;		ji->ea.size = 0;	}	inode->i_blocks += LBLK2PBLK(inode->i_sb, new_blocks - old_blocks);	rc = txCommit(tid, 1, &inode, 0);	txEnd(tid);	up(&ji->commit_sem);	return rc;}static int can_set_xattr(struct inode *inode, const char *name,			 void *value, size_t value_len){	if (IS_RDONLY(inode))		return -EROFS;	if (IS_IMMUTABLE(inode) || IS_APPEND(inode) || S_ISLNK(inode->i_mode))		return -EPERM;	if((strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) != 0) &&	   (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) != 0))		return -EOPNOTSUPP;	if (!S_ISREG(inode->i_mode) &&	    (!S_ISDIR(inode->i_mode) || inode->i_mode &S_ISVTX))		return -EPERM;	return permission(inode, MAY_WRITE);}int __jfs_setxattr(struct inode *inode, const char *name, void *value,		   size_t value_len, int flags){	struct jfs_ea_list *ealist;	struct jfs_ea *ea, *old_ea = NULL, *next_ea = NULL;	struct ea_buffer ea_buf;	int old_ea_size = 0;	int xattr_size;	int new_size;	int namelen = strlen(name);	char *os2name = NULL;	int found = 0;	int rc;	int length;	if ((rc = can_set_xattr(inode, name, value, value_len)))		return rc;	if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {		os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1,				  GFP_KERNEL);		if (!os2name)			return -ENOMEM;		strcpy(os2name, name + XATTR_OS2_PREFIX_LEN);		name = os2name;		namelen -= XATTR_OS2_PREFIX_LEN;	}	xattr_size = ea_get(inode, &ea_buf, 0);	if (xattr_size < 0) {		rc = xattr_size;		goto out;	}      again:	ealist = (struct jfs_ea_list *) ea_buf.xattr;	new_size = sizeof (struct jfs_ea_list);	if (xattr_size) {		for (ea = FIRST_EA(ealist); ea < END_EALIST(ealist);		     ea = NEXT_EA(ea)) {			if ((namelen == ea->namelen) &&			    (memcmp(name, ea->name, namelen) == 0)) {				found = 1;				if (flags & XATTR_CREATE) {					rc = -EEXIST;					goto release;				}				old_ea = ea;				old_ea_size = EA_SIZE(ea);				next_ea = NEXT_EA(ea);			} else				new_size += EA_SIZE(ea);		}	}	if (!found) {		if (flags & XATTR_REPLACE) {			rc = -ENODATA;			goto release;		}		if (value == NULL) {			rc = 0;			goto release;		}	}	if (value)		new_size += sizeof (struct jfs_ea) + namelen + 1 + value_len;	if (new_size > ea_buf.max_size) {		/*		 * We need to allocate more space for merged ea list.		 * We should only have loop to again: once.		 */		ea_release(inode, &ea_buf);		xattr_size = ea_get(inode, &ea_buf, new_size);		if (xattr_size < 0) {			rc = xattr_size;			goto out;		}		goto again;	}	/* Remove old ea of the same name */	if (found) {		/* number of bytes following target EA */		length = (char *) END_EALIST(ealist) - (char *) next_ea;		if (length > 0)			memmove(old_ea, next_ea, length);		xattr_size -= old_ea_size;	}	/* Add new entry to the end */	if (value) {		if (xattr_size == 0)			/* Completely new ea list */			xattr_size = sizeof (struct jfs_ea_list);		ea = (struct jfs_ea *) ((char *) ealist + xattr_size);		ea->flag = 0;		ea->namelen = namelen;		ea->valuelen = (cpu_to_le16(value_len));		memcpy(ea->name, name, namelen);		ea->name[namelen] = 0;		if (value_len)			memcpy(&ea->name[namelen + 1], value, value_len);		xattr_size += EA_SIZE(ea);	}	/* DEBUG - If we did this right, these number match */	if (xattr_size != new_size) {		printk(KERN_ERR		       "jfs_xsetattr: xattr_size = %d, new_size = %d\n",		       xattr_size, new_size);		rc = -EINVAL;		goto release;	}	/*	 * If we're left with an empty list, there's no ea	 */	if (new_size == sizeof (struct jfs_ea_list))		new_size = 0;	ealist->size = cpu_to_le32(new_size);	rc = ea_put(inode, &ea_buf, new_size);	goto out;      release:	ea_release(inode, &ea_buf);      out:	if (os2name)		kfree(os2name);	return rc;}int jfs_setxattr(struct dentry *dentry, const char *name, void *value,		 size_t value_len, int flags){	if (value == NULL) {	/* empty EA, do not remove */		value = "";		value_len = 0;	}	return __jfs_setxattr(dentry->d_inode, name, value, value_len, flags);}static inline int can_get_xattr(struct inode *inode, const char *name){	if(strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) == 0)		return 0;	return permission(inode, MAY_READ);}ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data,		       size_t buf_size){	struct jfs_ea_list *ealist;	struct jfs_ea *ea;	struct ea_buffer ea_buf;	int xattr_size;	ssize_t size;	int namelen = strlen(name);	char *os2name = NULL;	int rc;	char *value;	if ((rc = can_get_xattr(inode, name)))		return rc;	if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {		os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1,				  GFP_KERNEL);		if (!os2name)			return -ENOMEM;		strcpy(os2name, name + XATTR_OS2_PREFIX_LEN);		name = os2name;		namelen -= XATTR_OS2_PREFIX_LEN;	}	xattr_size = ea_get(inode, &ea_buf, 0);	if (xattr_size < 0) {		size = xattr_size;		goto out;	}	if (xattr_size == 0)		goto not_found;	ealist = (struct jfs_ea_list *) ea_buf.xattr;	/* Find the named attribute */	for (ea = FIRST_EA(ealist); ea < END_EALIST(ealist); ea = NEXT_EA(ea))		if ((namelen == ea->namelen) &&		    memcmp(name, ea->name, namelen) == 0) {			/* Found it */			size = le16_to_cpu(ea->valuelen);			if (!data)				goto release;			else if (size > buf_size) {				size = -ERANGE;				goto release;			}			value = ((char *) &ea->name) + ea->namelen + 1;			memcpy(data, value, size);			goto release;		}      not_found:	size = -ENODATA;      release:	ea_release(inode, &ea_buf);      out:	if (os2name)		kfree(os2name);	return size;}ssize_t jfs_getxattr(struct dentry *dentry, const char *name, void *data,		     size_t buf_size){	return __jfs_getxattr(dentry->d_inode, name, data, buf_size);}ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size){	struct inode *inode = dentry->d_inode;	char *buffer;	ssize_t size = 0;	int xattr_size;	struct jfs_ea_list *ealist;	struct jfs_ea *ea;	struct ea_buffer ea_buf;	xattr_size = ea_get(inode, &ea_buf, 0);	if (xattr_size < 0) {		size = xattr_size;		goto out;	}	if (xattr_size == 0)		goto release;	ealist = (struct jfs_ea_list *) ea_buf.xattr;	/* compute required size of list */	for (ea = FIRST_EA(ealist); ea < END_EALIST(ealist); ea = NEXT_EA(ea))		size += name_size(ea) + 1;	if (!data)		goto release;	if (size > buf_size) {		size = -ERANGE;		goto release;	}	/* Copy attribute names to buffer */	buffer = data;	for (ea = FIRST_EA(ealist); ea < END_EALIST(ealist); ea = NEXT_EA(ea)) {		int namelen = copy_name(buffer, ea);		buffer += namelen + 1;	}      release:	ea_release(inode, &ea_buf);      out:	return size;}int jfs_removexattr(struct dentry *dentry, const char *name){	return __jfs_setxattr(dentry->d_inode, name, 0, 0, XATTR_REPLACE);}#endif	/* JFS_XATTR */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -