- int err = 0;
- struct file *fp;
- struct page *page;
- char *data;
- struct address_space *mapping;
- size_t file_pos = 0;
- size_t buffer_pos = 0;
- struct inode *xinode;
- struct iattr newattrs;
- __u32 xahash = 0;
-
- if (IS_RDONLY (inode))
- return -EROFS;
-
- if (IS_IMMUTABLE (inode) || IS_APPEND (inode))
- return -EPERM;
-
- if (get_inode_sd_version (inode) == STAT_DATA_V1)
- return -EOPNOTSUPP;
-
- /* Empty xattrs are ok, they're just empty files, no hash */
- if (buffer && buffer_size)
- xahash = xattr_hash (buffer, buffer_size);
-
-open_file:
- fp = open_xa_file (inode, name, flags);
- if (IS_ERR (fp)) {
- err = PTR_ERR (fp);
- goto out;
- }
-
- xinode = fp->f_dentry->d_inode;
- REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
-
- /* we need to copy it off.. */
- if (xinode->i_nlink > 1) {
- fput(fp);
- err = reiserfs_xattr_del (inode, name);
- if (err < 0)
- goto out;
- /* We just killed the old one, we're not replacing anymore */
- if (flags & XATTR_REPLACE)
- flags &= ~XATTR_REPLACE;
- goto open_file;
- }
-
- /* Resize it so we're ok to write there */
- newattrs.ia_size = buffer_size;
- newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
- down (&xinode->i_sem);
- err = notify_change(fp->f_dentry, &newattrs);
- if (err)
- goto out_filp;
-
- mapping = xinode->i_mapping;
- while (buffer_pos < buffer_size || buffer_pos == 0) {
- size_t chunk;
- size_t skip = 0;
- size_t page_offset = (file_pos & (PAGE_CACHE_SIZE - 1));
- if (buffer_size - buffer_pos > PAGE_CACHE_SIZE)
- chunk = PAGE_CACHE_SIZE;
- else
- chunk = buffer_size - buffer_pos;
-
- page = reiserfs_get_page (xinode, file_pos >> PAGE_CACHE_SHIFT);
- if (IS_ERR (page)) {
- err = PTR_ERR (page);
- goto out_filp;
- }
-
- lock_page (page);
- data = page_address (page);
-
- if (file_pos == 0) {
- struct reiserfs_xattr_header *rxh;
- skip = file_pos = sizeof (struct reiserfs_xattr_header);
- if (chunk + skip > PAGE_CACHE_SIZE)
- chunk = PAGE_CACHE_SIZE - skip;
- rxh = (struct reiserfs_xattr_header *)data;
- rxh->h_magic = cpu_to_le32 (REISERFS_XATTR_MAGIC);
- rxh->h_hash = cpu_to_le32 (xahash);
- }
-
- err = mapping->a_ops->prepare_write (fp, page, page_offset,
- page_offset + chunk + skip);
- if (!err) {
- if (buffer)
- memcpy (data + skip, buffer + buffer_pos, chunk);
- err = mapping->a_ops->commit_write (fp, page, page_offset,
- page_offset + chunk + skip);
+ int err = 0;
+ struct file *fp;
+ struct page *page;
+ char *data;
+ struct address_space *mapping;
+ size_t file_pos = 0;
+ size_t buffer_pos = 0;
+ struct inode *xinode;
+ struct iattr newattrs;
+ __u32 xahash = 0;
+
+ if (get_inode_sd_version(inode) == STAT_DATA_V1)
+ return -EOPNOTSUPP;
+
+ /* Empty xattrs are ok, they're just empty files, no hash */
+ if (buffer && buffer_size)
+ xahash = xattr_hash(buffer, buffer_size);
+
+ open_file:
+ fp = open_xa_file(inode, name, flags);
+ if (IS_ERR(fp)) {
+ err = PTR_ERR(fp);
+ goto out;
+ }
+
+ xinode = fp->f_dentry->d_inode;
+ REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
+
+ /* we need to copy it off.. */
+ if (xinode->i_nlink > 1) {
+ fput(fp);
+ err = reiserfs_xattr_del(inode, name);
+ if (err < 0)
+ goto out;
+ /* We just killed the old one, we're not replacing anymore */
+ if (flags & XATTR_REPLACE)
+ flags &= ~XATTR_REPLACE;
+ goto open_file;
+ }
+
+ /* Resize it so we're ok to write there */
+ newattrs.ia_size = buffer_size;
+ newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
+ mutex_lock(&xinode->i_mutex);
+ err = notify_change(fp->f_dentry, &newattrs);
+ if (err)
+ goto out_filp;
+
+ mapping = xinode->i_mapping;
+ while (buffer_pos < buffer_size || buffer_pos == 0) {
+ size_t chunk;
+ size_t skip = 0;
+ size_t page_offset = (file_pos & (PAGE_CACHE_SIZE - 1));
+ if (buffer_size - buffer_pos > PAGE_CACHE_SIZE)
+ chunk = PAGE_CACHE_SIZE;
+ else
+ chunk = buffer_size - buffer_pos;
+
+ page = reiserfs_get_page(xinode, file_pos >> PAGE_CACHE_SHIFT);
+ if (IS_ERR(page)) {
+ err = PTR_ERR(page);
+ goto out_filp;
+ }
+
+ lock_page(page);
+ data = page_address(page);
+
+ if (file_pos == 0) {
+ struct reiserfs_xattr_header *rxh;
+ skip = file_pos = sizeof(struct reiserfs_xattr_header);
+ if (chunk + skip > PAGE_CACHE_SIZE)
+ chunk = PAGE_CACHE_SIZE - skip;
+ rxh = (struct reiserfs_xattr_header *)data;
+ rxh->h_magic = cpu_to_le32(REISERFS_XATTR_MAGIC);
+ rxh->h_hash = cpu_to_le32(xahash);
+ }
+
+ err = mapping->a_ops->prepare_write(fp, page, page_offset,
+ page_offset + chunk + skip);
+ if (!err) {
+ if (buffer)
+ memcpy(data + skip, buffer + buffer_pos, chunk);
+ err =
+ mapping->a_ops->commit_write(fp, page, page_offset,
+ page_offset + chunk +
+ skip);
+ }
+ unlock_page(page);
+ reiserfs_put_page(page);
+ buffer_pos += chunk;
+ file_pos += chunk;
+ skip = 0;
+ if (err || buffer_size == 0 || !buffer)
+ break;
+ }
+
+ /* We can't mark the inode dirty if it's not hashed. This is the case
+ * when we're inheriting the default ACL. If we dirty it, the inode
+ * gets marked dirty, but won't (ever) make it onto the dirty list until
+ * it's synced explicitly to clear I_DIRTY. This is bad. */
+ if (!hlist_unhashed(&inode->i_hash)) {
+ inode->i_ctime = CURRENT_TIME_SEC;
+ mark_inode_dirty(inode);