diff options
Diffstat (limited to 'fs/reiserfs/xattr.c')
| -rw-r--r-- | fs/reiserfs/xattr.c | 2173 | 
1 files changed, 1087 insertions, 1086 deletions
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 45582fe8b466..e386d3db3051 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c  | |||
| @@ -51,67 +51,68 @@ | |||
| 51 | #define PRIVROOT_NAME ".reiserfs_priv" | 51 | #define PRIVROOT_NAME ".reiserfs_priv" | 
| 52 | #define XAROOT_NAME "xattrs" | 52 | #define XAROOT_NAME "xattrs" | 
| 53 | 53 | ||
| 54 | static struct reiserfs_xattr_handler *find_xattr_handler_prefix (const char *prefix); | 54 | static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char | 
| 55 | *prefix); | ||
| 55 | 56 | ||
| 56 | static struct dentry * | 57 | static struct dentry *create_xa_root(struct super_block *sb) | 
| 57 | create_xa_root (struct super_block *sb) | ||
| 58 | { | 58 | { | 
| 59 | struct dentry *privroot = dget (REISERFS_SB(sb)->priv_root); | 59 | struct dentry *privroot = dget(REISERFS_SB(sb)->priv_root); | 
| 60 | struct dentry *xaroot; | 60 | struct dentry *xaroot; | 
| 61 | 61 | ||
| 62 | /* This needs to be created at mount-time */ | 62 | /* This needs to be created at mount-time */ | 
| 63 | if (!privroot) | 63 | if (!privroot) | 
| 64 | return ERR_PTR(-EOPNOTSUPP); | 64 | return ERR_PTR(-EOPNOTSUPP); | 
| 65 | 65 | ||
| 66 | xaroot = lookup_one_len (XAROOT_NAME, privroot, strlen (XAROOT_NAME)); | 66 | xaroot = lookup_one_len(XAROOT_NAME, privroot, strlen(XAROOT_NAME)); | 
| 67 | if (IS_ERR (xaroot)) { | 67 | if (IS_ERR(xaroot)) { | 
| 68 | goto out; | 68 | goto out; | 
| 69 | } else if (!xaroot->d_inode) { | 69 | } else if (!xaroot->d_inode) { | 
| 70 | int err; | 70 | int err; | 
| 71 | down (&privroot->d_inode->i_sem); | 71 | down(&privroot->d_inode->i_sem); | 
| 72 | err = privroot->d_inode->i_op->mkdir (privroot->d_inode, xaroot, 0700); | 72 | err = | 
| 73 | up (&privroot->d_inode->i_sem); | 73 | privroot->d_inode->i_op->mkdir(privroot->d_inode, xaroot, | 
| 74 | 74 | 0700); | |
| 75 | if (err) { | 75 | up(&privroot->d_inode->i_sem); | 
| 76 | dput (xaroot); | 76 | |
| 77 | dput (privroot); | 77 | if (err) { | 
| 78 | return ERR_PTR (err); | 78 | dput(xaroot); | 
| 79 | } | 79 | dput(privroot); | 
| 80 | REISERFS_SB(sb)->xattr_root = dget (xaroot); | 80 | return ERR_PTR(err); | 
| 81 | } | 81 | } | 
| 82 | 82 | REISERFS_SB(sb)->xattr_root = dget(xaroot); | |
| 83 | out: | 83 | } | 
| 84 | dput (privroot); | 84 | |
| 85 | return xaroot; | 85 | out: | 
| 86 | dput(privroot); | ||
| 87 | return xaroot; | ||
| 86 | } | 88 | } | 
| 87 | 89 | ||
| 88 | /* This will return a dentry, or error, refering to the xa root directory. | 90 | /* This will return a dentry, or error, refering to the xa root directory. | 
| 89 | * If the xa root doesn't exist yet, the dentry will be returned without | 91 | * If the xa root doesn't exist yet, the dentry will be returned without | 
| 90 | * an associated inode. This dentry can be used with ->mkdir to create | 92 | * an associated inode. This dentry can be used with ->mkdir to create | 
| 91 | * the xa directory. */ | 93 | * the xa directory. */ | 
| 92 | static struct dentry * | 94 | static struct dentry *__get_xa_root(struct super_block *s) | 
| 93 | __get_xa_root (struct super_block *s) | ||
| 94 | { | 95 | { | 
| 95 | struct dentry *privroot = dget (REISERFS_SB(s)->priv_root); | 96 | struct dentry *privroot = dget(REISERFS_SB(s)->priv_root); | 
| 96 | struct dentry *xaroot = NULL; | 97 | struct dentry *xaroot = NULL; | 
| 97 | 98 | ||
| 98 | if (IS_ERR (privroot) || !privroot) | 99 | if (IS_ERR(privroot) || !privroot) | 
| 99 | return privroot; | 100 | return privroot; | 
| 100 | 101 | ||
| 101 | xaroot = lookup_one_len (XAROOT_NAME, privroot, strlen (XAROOT_NAME)); | 102 | xaroot = lookup_one_len(XAROOT_NAME, privroot, strlen(XAROOT_NAME)); | 
| 102 | if (IS_ERR (xaroot)) { | 103 | if (IS_ERR(xaroot)) { | 
| 103 | goto out; | 104 | goto out; | 
| 104 | } else if (!xaroot->d_inode) { | 105 | } else if (!xaroot->d_inode) { | 
| 105 | dput (xaroot); | 106 | dput(xaroot); | 
| 106 | xaroot = NULL; | 107 | xaroot = NULL; | 
| 107 | goto out; | 108 | goto out; | 
| 108 | } | 109 | } | 
| 109 | 110 | ||
| 110 | REISERFS_SB(s)->xattr_root = dget (xaroot); | 111 | REISERFS_SB(s)->xattr_root = dget(xaroot); | 
| 111 | 112 | ||
| 112 | out: | 113 | out: | 
| 113 | dput (privroot); | 114 | dput(privroot); | 
| 114 | return xaroot; | 115 | return xaroot; | 
| 115 | } | 116 | } | 
| 116 | 117 | ||
| 117 | /* Returns the dentry (or NULL) referring to the root of the extended | 118 | /* Returns the dentry (or NULL) referring to the root of the extended | 
| @@ -119,147 +120,145 @@ out: | |||
| 119 | * Otherwise, we attempt to retreive it from disk. It may also return | 120 | * Otherwise, we attempt to retreive it from disk. It may also return | 
| 120 | * a pointer-encoded error. | 121 | * a pointer-encoded error. | 
| 121 | */ | 122 | */ | 
| 122 | static inline struct dentry * | 123 | static inline struct dentry *get_xa_root(struct super_block *s) | 
| 123 | get_xa_root (struct super_block *s) | ||
| 124 | { | 124 | { | 
| 125 | struct dentry *dentry = dget (REISERFS_SB(s)->xattr_root); | 125 | struct dentry *dentry = dget(REISERFS_SB(s)->xattr_root); | 
| 126 | 126 | ||
| 127 | if (!dentry) | 127 | if (!dentry) | 
| 128 | dentry = __get_xa_root (s); | 128 | dentry = __get_xa_root(s); | 
| 129 | 129 | ||
| 130 | return dentry; | 130 | return dentry; | 
| 131 | } | 131 | } | 
| 132 | 132 | ||
| 133 | /* Opens the directory corresponding to the inode's extended attribute store. | 133 | /* Opens the directory corresponding to the inode's extended attribute store. | 
| 134 | * If flags allow, the tree to the directory may be created. If creation is | 134 | * If flags allow, the tree to the directory may be created. If creation is | 
| 135 | * prohibited, -ENODATA is returned. */ | 135 | * prohibited, -ENODATA is returned. */ | 
| 136 | static struct dentry * | 136 | static struct dentry *open_xa_dir(const struct inode *inode, int flags) | 
| 137 | open_xa_dir (const struct inode *inode, int flags) | ||
| 138 | { | 137 | { | 
| 139 | struct dentry *xaroot, *xadir; | 138 | struct dentry *xaroot, *xadir; | 
| 140 | char namebuf[17]; | 139 | char namebuf[17]; | 
| 141 | 140 | ||
| 142 | xaroot = get_xa_root (inode->i_sb); | 141 | xaroot = get_xa_root(inode->i_sb); | 
| 143 | if (IS_ERR (xaroot)) { | 142 | if (IS_ERR(xaroot)) { | 
| 144 | return xaroot; | 143 | return xaroot; | 
| 145 | } else if (!xaroot) { | 144 | } else if (!xaroot) { | 
| 146 | if (flags == 0 || flags & XATTR_CREATE) { | 145 | if (flags == 0 || flags & XATTR_CREATE) { | 
| 147 | xaroot = create_xa_root (inode->i_sb); | 146 | xaroot = create_xa_root(inode->i_sb); | 
| 148 | if (IS_ERR (xaroot)) | 147 | if (IS_ERR(xaroot)) | 
| 149 | return xaroot; | 148 | return xaroot; | 
| 150 | } | 149 | } | 
| 151 | if (!xaroot) | 150 | if (!xaroot) | 
| 152 | return ERR_PTR (-ENODATA); | 151 | return ERR_PTR(-ENODATA); | 
| 153 | } | 152 | } | 
| 154 | 153 | ||
| 155 | /* ok, we have xaroot open */ | 154 | /* ok, we have xaroot open */ | 
| 156 | 155 | ||
| 157 | snprintf (namebuf, sizeof (namebuf), "%X.%X", | 156 | snprintf(namebuf, sizeof(namebuf), "%X.%X", | 
| 158 | le32_to_cpu (INODE_PKEY (inode)->k_objectid), | 157 | le32_to_cpu(INODE_PKEY(inode)->k_objectid), | 
| 159 | inode->i_generation); | 158 | inode->i_generation); | 
| 160 | xadir = lookup_one_len (namebuf, xaroot, strlen (namebuf)); | 159 | xadir = lookup_one_len(namebuf, xaroot, strlen(namebuf)); | 
| 161 | if (IS_ERR (xadir)) { | 160 | if (IS_ERR(xadir)) { | 
| 162 | dput (xaroot); | 161 | dput(xaroot); | 
| 163 | return xadir; | 162 | return xadir; | 
| 164 | } | 163 | } | 
| 165 | 164 | ||
| 166 | if (!xadir->d_inode) { | 165 | if (!xadir->d_inode) { | 
| 167 | int err; | 166 | int err; | 
| 168 | if (flags == 0 || flags & XATTR_CREATE) { | 167 | if (flags == 0 || flags & XATTR_CREATE) { | 
| 169 | /* Although there is nothing else trying to create this directory, | 168 | /* Although there is nothing else trying to create this directory, | 
| 170 | * another directory with the same hash may be created, so we need | 169 | * another directory with the same hash may be created, so we need | 
| 171 | * to protect against that */ | 170 | * to protect against that */ | 
| 172 | err = xaroot->d_inode->i_op->mkdir (xaroot->d_inode, xadir, 0700); | 171 | err = | 
| 173 | if (err) { | 172 | xaroot->d_inode->i_op->mkdir(xaroot->d_inode, xadir, | 
| 174 | dput (xaroot); | 173 | 0700); | 
| 175 | dput (xadir); | 174 | if (err) { | 
| 176 | return ERR_PTR (err); | 175 | dput(xaroot); | 
| 177 | } | 176 | dput(xadir); | 
| 178 | } | 177 | return ERR_PTR(err); | 
| 179 | if (!xadir->d_inode) { | 178 | } | 
| 180 | dput (xaroot); | 179 | } | 
| 181 | dput (xadir); | 180 | if (!xadir->d_inode) { | 
| 182 | return ERR_PTR (-ENODATA); | 181 | dput(xaroot); | 
| 183 | } | 182 | dput(xadir); | 
| 184 | } | 183 | return ERR_PTR(-ENODATA); | 
| 185 | 184 | } | |
| 186 | dput (xaroot); | 185 | } | 
| 187 | return xadir; | 186 | |
| 187 | dput(xaroot); | ||
| 188 | return xadir; | ||
| 188 | } | 189 | } | 
| 189 | 190 | ||
| 190 | /* Returns a dentry corresponding to a specific extended attribute file | 191 | /* Returns a dentry corresponding to a specific extended attribute file | 
| 191 | * for the inode. If flags allow, the file is created. Otherwise, a | 192 | * for the inode. If flags allow, the file is created. Otherwise, a | 
| 192 | * valid or negative dentry, or an error is returned. */ | 193 | * valid or negative dentry, or an error is returned. */ | 
| 193 | static struct dentry * | 194 | static struct dentry *get_xa_file_dentry(const struct inode *inode, | 
| 194 | get_xa_file_dentry (const struct inode *inode, const char *name, int flags) | 195 | const char *name, int flags) | 
| 195 | { | 196 | { | 
| 196 | struct dentry *xadir, *xafile; | 197 | struct dentry *xadir, *xafile; | 
| 197 | int err = 0; | 198 | int err = 0; | 
| 198 | 199 | ||
| 199 | xadir = open_xa_dir (inode, flags); | 200 | xadir = open_xa_dir(inode, flags); | 
| 200 | if (IS_ERR (xadir)) { | 201 | if (IS_ERR(xadir)) { | 
| 201 | return ERR_PTR (PTR_ERR (xadir)); | 202 | return ERR_PTR(PTR_ERR(xadir)); | 
| 202 | } else if (xadir && !xadir->d_inode) { | 203 | } else if (xadir && !xadir->d_inode) { | 
| 203 | dput (xadir); | 204 | dput(xadir); | 
| 204 | return ERR_PTR (-ENODATA); | 205 | return ERR_PTR(-ENODATA); | 
| 205 | } | 206 | } | 
| 206 | 207 | ||
| 207 | xafile = lookup_one_len (name, xadir, strlen (name)); | 208 | xafile = lookup_one_len(name, xadir, strlen(name)); | 
| 208 | if (IS_ERR (xafile)) { | 209 | if (IS_ERR(xafile)) { | 
| 209 | dput (xadir); | 210 | dput(xadir); | 
| 210 | return ERR_PTR (PTR_ERR (xafile)); | 211 | return ERR_PTR(PTR_ERR(xafile)); | 
| 211 | } | 212 | } | 
| 212 | 213 | ||
| 213 | if (xafile->d_inode) { /* file exists */ | 214 | if (xafile->d_inode) { /* file exists */ | 
| 214 | if (flags & XATTR_CREATE) { | 215 | if (flags & XATTR_CREATE) { | 
| 215 | err = -EEXIST; | 216 | err = -EEXIST; | 
| 216 | dput (xafile); | 217 | dput(xafile); | 
| 217 | goto out; | 218 | goto out; | 
| 218 | } | 219 | } | 
| 219 | } else if (flags & XATTR_REPLACE || flags & FL_READONLY) { | 220 | } else if (flags & XATTR_REPLACE || flags & FL_READONLY) { | 
| 220 | goto out; | 221 | goto out; | 
| 221 | } else { | 222 | } else { | 
| 222 | /* inode->i_sem is down, so nothing else can try to create | 223 | /* inode->i_sem is down, so nothing else can try to create | 
| 223 | * the same xattr */ | 224 | * the same xattr */ | 
| 224 | err = xadir->d_inode->i_op->create (xadir->d_inode, xafile, | 225 | err = xadir->d_inode->i_op->create(xadir->d_inode, xafile, | 
| 225 | 0700|S_IFREG, NULL); | 226 | 0700 | S_IFREG, NULL); | 
| 226 | 227 | ||
| 227 | if (err) { | 228 | if (err) { | 
| 228 | dput (xafile); | 229 | dput(xafile); | 
| 229 | goto out; | 230 | goto out; | 
| 230 | } | 231 | } | 
| 231 | } | 232 | } | 
| 232 | |||
| 233 | out: | ||
| 234 | dput (xadir); | ||
| 235 | if (err) | ||
| 236 | xafile = ERR_PTR (err); | ||
| 237 | return xafile; | ||
| 238 | } | ||
| 239 | 233 | ||
| 234 | out: | ||
| 235 | dput(xadir); | ||
| 236 | if (err) | ||
| 237 | xafile = ERR_PTR(err); | ||
| 238 | return xafile; | ||
| 239 | } | ||
| 240 | 240 | ||
| 241 | /* Opens a file pointer to the attribute associated with inode */ | 241 | /* Opens a file pointer to the attribute associated with inode */ | 
| 242 | static struct file * | 242 | static struct file *open_xa_file(const struct inode *inode, const char *name, | 
| 243 | open_xa_file (const struct inode *inode, const char *name, int flags) | 243 | int flags) | 
| 244 | { | 244 | { | 
| 245 | struct dentry *xafile; | 245 | struct dentry *xafile; | 
| 246 | struct file *fp; | 246 | struct file *fp; | 
| 247 | 247 | ||
| 248 | xafile = get_xa_file_dentry (inode, name, flags); | 248 | xafile = get_xa_file_dentry(inode, name, flags); | 
| 249 | if (IS_ERR (xafile)) | 249 | if (IS_ERR(xafile)) | 
| 250 | return ERR_PTR (PTR_ERR (xafile)); | 250 | return ERR_PTR(PTR_ERR(xafile)); | 
| 251 | else if (!xafile->d_inode) { | 251 | else if (!xafile->d_inode) { | 
| 252 | dput (xafile); | 252 | dput(xafile); | 
| 253 | return ERR_PTR (-ENODATA); | 253 | return ERR_PTR(-ENODATA); | 
| 254 | } | 254 | } | 
| 255 | 255 | ||
| 256 | fp = dentry_open (xafile, NULL, O_RDWR); | 256 | fp = dentry_open(xafile, NULL, O_RDWR); | 
| 257 | /* dentry_open dputs the dentry if it fails */ | 257 | /* dentry_open dputs the dentry if it fails */ | 
| 258 | 258 | ||
| 259 | return fp; | 259 | return fp; | 
| 260 | } | 260 | } | 
| 261 | 261 | ||
| 262 | |||
| 263 | /* | 262 | /* | 
| 264 | * this is very similar to fs/reiserfs/dir.c:reiserfs_readdir, but | 263 | * this is very similar to fs/reiserfs/dir.c:reiserfs_readdir, but | 
| 265 | * we need to drop the path before calling the filldir struct. That | 264 | * we need to drop the path before calling the filldir struct. That | 
| @@ -273,139 +272,146 @@ open_xa_file (const struct inode *inode, const char *name, int flags) | |||
| 273 | * we're called with i_sem held, so there are no worries about the directory | 272 | * we're called with i_sem held, so there are no worries about the directory | 
| 274 | * changing underneath us. | 273 | * changing underneath us. | 
| 275 | */ | 274 | */ | 
| 276 | static int __xattr_readdir(struct file * filp, void * dirent, filldir_t filldir) | 275 | static int __xattr_readdir(struct file *filp, void *dirent, filldir_t filldir) | 
| 277 | { | 276 | { | 
| 278 | struct inode *inode = filp->f_dentry->d_inode; | 277 | struct inode *inode = filp->f_dentry->d_inode; | 
| 279 | struct cpu_key pos_key; /* key of current position in the directory (key of directory entry) */ | 278 | struct cpu_key pos_key; /* key of current position in the directory (key of directory entry) */ | 
| 280 | INITIALIZE_PATH (path_to_entry); | 279 | INITIALIZE_PATH(path_to_entry); | 
| 281 | struct buffer_head * bh; | 280 | struct buffer_head *bh; | 
| 282 | int entry_num; | 281 | int entry_num; | 
| 283 | struct item_head * ih, tmp_ih; | 282 | struct item_head *ih, tmp_ih; | 
| 284 | int search_res; | 283 | int search_res; | 
| 285 | char * local_buf; | 284 | char *local_buf; | 
| 286 | loff_t next_pos; | 285 | loff_t next_pos; | 
| 287 | char small_buf[32] ; /* avoid kmalloc if we can */ | 286 | char small_buf[32]; /* avoid kmalloc if we can */ | 
| 288 | struct reiserfs_de_head *deh; | 287 | struct reiserfs_de_head *deh; | 
| 289 | int d_reclen; | 288 | int d_reclen; | 
| 290 | char * d_name; | 289 | char *d_name; | 
| 291 | off_t d_off; | 290 | off_t d_off; | 
| 292 | ino_t d_ino; | 291 | ino_t d_ino; | 
| 293 | struct reiserfs_dir_entry de; | 292 | struct reiserfs_dir_entry de; | 
| 294 | 293 | ||
| 295 | 294 | /* form key for search the next directory entry using f_pos field of | |
| 296 | /* form key for search the next directory entry using f_pos field of | 295 | file structure */ | 
| 297 | file structure */ | 296 | next_pos = max_reiserfs_offset(inode); | 
| 298 | next_pos = max_reiserfs_offset(inode); | 297 | |
| 299 | 298 | while (1) { | |
| 300 | while (1) { | 299 | research: | 
| 301 | research: | 300 | if (next_pos <= DOT_DOT_OFFSET) | 
| 302 | if (next_pos <= DOT_DOT_OFFSET) | 301 | break; | 
| 303 | break; | 302 | make_cpu_key(&pos_key, inode, next_pos, TYPE_DIRENTRY, 3); | 
| 304 | make_cpu_key (&pos_key, inode, next_pos, TYPE_DIRENTRY, 3); | 303 | |
| 305 | 304 | search_res = | |
| 306 | search_res = search_by_entry_key(inode->i_sb, &pos_key, &path_to_entry, &de); | 305 | search_by_entry_key(inode->i_sb, &pos_key, &path_to_entry, | 
| 307 | if (search_res == IO_ERROR) { | 306 | &de); | 
| 308 | // FIXME: we could just skip part of directory which could | 307 | if (search_res == IO_ERROR) { | 
| 309 | // not be read | 308 | // FIXME: we could just skip part of directory which could | 
| 310 | pathrelse(&path_to_entry); | 309 | // not be read | 
| 311 | return -EIO; | 310 | pathrelse(&path_to_entry); | 
| 312 | } | 311 | return -EIO; | 
| 313 | 312 | } | |
| 314 | if (search_res == NAME_NOT_FOUND) | ||
| 315 | de.de_entry_num--; | ||
| 316 | 313 | ||
| 317 | set_de_name_and_namelen(&de); | 314 | if (search_res == NAME_NOT_FOUND) | 
| 318 | entry_num = de.de_entry_num; | 315 | de.de_entry_num--; | 
| 319 | deh = &(de.de_deh[entry_num]); | ||
| 320 | 316 | ||
| 321 | bh = de.de_bh; | 317 | set_de_name_and_namelen(&de); | 
| 322 | ih = de.de_ih; | 318 | entry_num = de.de_entry_num; | 
| 319 | deh = &(de.de_deh[entry_num]); | ||
| 323 | 320 | ||
| 324 | if (!is_direntry_le_ih(ih)) { | 321 | bh = de.de_bh; | 
| 325 | reiserfs_warning(inode->i_sb, "not direntry %h", ih); | 322 | ih = de.de_ih; | 
| 326 | break; | ||
| 327 | } | ||
| 328 | copy_item_head(&tmp_ih, ih); | ||
| 329 | 323 | ||
| 330 | /* we must have found item, that is item of this directory, */ | 324 | if (!is_direntry_le_ih(ih)) { | 
| 331 | RFALSE( COMP_SHORT_KEYS (&(ih->ih_key), &pos_key), | 325 | reiserfs_warning(inode->i_sb, "not direntry %h", ih); | 
| 332 | "vs-9000: found item %h does not match to dir we readdir %K", | 326 | break; | 
| 333 | ih, &pos_key); | 327 | } | 
| 328 | copy_item_head(&tmp_ih, ih); | ||
| 334 | 329 | ||
| 335 | if (deh_offset(deh) <= DOT_DOT_OFFSET) { | 330 | /* we must have found item, that is item of this directory, */ | 
| 336 | break; | 331 | RFALSE(COMP_SHORT_KEYS(&(ih->ih_key), &pos_key), | 
| 337 | } | 332 | "vs-9000: found item %h does not match to dir we readdir %K", | 
| 333 | ih, &pos_key); | ||
| 338 | 334 | ||
| 339 | /* look for the previous entry in the directory */ | 335 | if (deh_offset(deh) <= DOT_DOT_OFFSET) { | 
| 340 | next_pos = deh_offset (deh) - 1; | 336 | break; | 
| 337 | } | ||
| 341 | 338 | ||
| 342 | if (!de_visible (deh)) | 339 | /* look for the previous entry in the directory */ | 
| 343 | /* it is hidden entry */ | 340 | next_pos = deh_offset(deh) - 1; | 
| 344 | continue; | ||
| 345 | 341 | ||
| 346 | d_reclen = entry_length(bh, ih, entry_num); | 342 | if (!de_visible(deh)) | 
| 347 | d_name = B_I_DEH_ENTRY_FILE_NAME (bh, ih, deh); | 343 | /* it is hidden entry */ | 
| 348 | d_off = deh_offset (deh); | 344 | continue; | 
| 349 | d_ino = deh_objectid (deh); | ||
| 350 | 345 | ||
| 351 | if (!d_name[d_reclen - 1]) | 346 | d_reclen = entry_length(bh, ih, entry_num); | 
| 352 | d_reclen = strlen (d_name); | 347 | d_name = B_I_DEH_ENTRY_FILE_NAME(bh, ih, deh); | 
| 348 | d_off = deh_offset(deh); | ||
| 349 | d_ino = deh_objectid(deh); | ||
| 353 | 350 | ||
| 354 | if (d_reclen > REISERFS_MAX_NAME(inode->i_sb->s_blocksize)){ | 351 | if (!d_name[d_reclen - 1]) | 
| 355 | /* too big to send back to VFS */ | 352 | d_reclen = strlen(d_name); | 
| 356 | continue ; | ||
| 357 | } | ||
| 358 | 353 | ||
| 359 | /* Ignore the .reiserfs_priv entry */ | 354 | if (d_reclen > REISERFS_MAX_NAME(inode->i_sb->s_blocksize)) { | 
| 360 | if (reiserfs_xattrs (inode->i_sb) && | 355 | /* too big to send back to VFS */ | 
| 361 | !old_format_only(inode->i_sb) && | 356 | continue; | 
| 362 | deh_objectid (deh) == le32_to_cpu (INODE_PKEY(REISERFS_SB(inode->i_sb)->priv_root->d_inode)->k_objectid)) | 357 | } | 
| 363 | continue; | ||
| 364 | 358 | ||
| 365 | if (d_reclen <= 32) { | 359 | /* Ignore the .reiserfs_priv entry */ | 
| 366 | local_buf = small_buf ; | 360 | if (reiserfs_xattrs(inode->i_sb) && | 
| 367 | } else { | 361 | !old_format_only(inode->i_sb) && | 
| 368 | local_buf = reiserfs_kmalloc(d_reclen, GFP_NOFS, inode->i_sb) ; | 362 | deh_objectid(deh) == | 
| 369 | if (!local_buf) { | 363 | le32_to_cpu(INODE_PKEY | 
| 370 | pathrelse (&path_to_entry); | 364 | (REISERFS_SB(inode->i_sb)->priv_root->d_inode)-> | 
| 371 | return -ENOMEM ; | 365 | k_objectid)) | 
| 372 | } | 366 | continue; | 
| 373 | if (item_moved (&tmp_ih, &path_to_entry)) { | 367 | |
| 374 | reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ; | 368 | if (d_reclen <= 32) { | 
| 375 | 369 | local_buf = small_buf; | |
| 376 | /* sigh, must retry. Do this same offset again */ | 370 | } else { | 
| 377 | next_pos = d_off; | 371 | local_buf = | 
| 378 | goto research; | 372 | reiserfs_kmalloc(d_reclen, GFP_NOFS, inode->i_sb); | 
| 379 | } | 373 | if (!local_buf) { | 
| 380 | } | 374 | pathrelse(&path_to_entry); | 
| 375 | return -ENOMEM; | ||
| 376 | } | ||
| 377 | if (item_moved(&tmp_ih, &path_to_entry)) { | ||
| 378 | reiserfs_kfree(local_buf, d_reclen, | ||
| 379 | inode->i_sb); | ||
| 380 | |||
| 381 | /* sigh, must retry. Do this same offset again */ | ||
| 382 | next_pos = d_off; | ||
| 383 | goto research; | ||
| 384 | } | ||
| 385 | } | ||
| 381 | 386 | ||
| 382 | // Note, that we copy name to user space via temporary | 387 | // Note, that we copy name to user space via temporary | 
| 383 | // buffer (local_buf) because filldir will block if | 388 | // buffer (local_buf) because filldir will block if | 
| 384 | // user space buffer is swapped out. At that time | 389 | // user space buffer is swapped out. At that time | 
| 385 | // entry can move to somewhere else | 390 | // entry can move to somewhere else | 
| 386 | memcpy (local_buf, d_name, d_reclen); | 391 | memcpy(local_buf, d_name, d_reclen); | 
| 387 | 392 | ||
| 388 | /* the filldir function might need to start transactions, | 393 | /* the filldir function might need to start transactions, | 
| 389 | * or do who knows what. Release the path now that we've | 394 | * or do who knows what. Release the path now that we've | 
| 390 | * copied all the important stuff out of the deh | 395 | * copied all the important stuff out of the deh | 
| 391 | */ | 396 | */ | 
| 392 | pathrelse (&path_to_entry); | 397 | pathrelse(&path_to_entry); | 
| 393 | 398 | ||
| 394 | if (filldir (dirent, local_buf, d_reclen, d_off, d_ino, | 399 | if (filldir(dirent, local_buf, d_reclen, d_off, d_ino, | 
| 395 | DT_UNKNOWN) < 0) { | 400 | DT_UNKNOWN) < 0) { | 
| 396 | if (local_buf != small_buf) { | 401 | if (local_buf != small_buf) { | 
| 397 | reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ; | 402 | reiserfs_kfree(local_buf, d_reclen, | 
| 398 | } | 403 | inode->i_sb); | 
| 399 | goto end; | 404 | } | 
| 400 | } | 405 | goto end; | 
| 401 | if (local_buf != small_buf) { | 406 | } | 
| 402 | reiserfs_kfree(local_buf, d_reclen, inode->i_sb) ; | 407 | if (local_buf != small_buf) { | 
| 403 | } | 408 | reiserfs_kfree(local_buf, d_reclen, inode->i_sb); | 
| 404 | } /* while */ | 409 | } | 
| 410 | } /* while */ | ||
| 405 | 411 | ||
| 406 | end: | 412 | end: | 
| 407 | pathrelse (&path_to_entry); | 413 | pathrelse(&path_to_entry); | 
| 408 | return 0; | 414 | return 0; | 
| 409 | } | 415 | } | 
| 410 | 416 | ||
| 411 | /* | 417 | /* | 
| @@ -417,63 +423,59 @@ end: | |||
| 417 | static | 423 | static | 
| 418 | int xattr_readdir(struct file *file, filldir_t filler, void *buf) | 424 | int xattr_readdir(struct file *file, filldir_t filler, void *buf) | 
| 419 | { | 425 | { | 
| 420 | struct inode *inode = file->f_dentry->d_inode; | 426 | struct inode *inode = file->f_dentry->d_inode; | 
| 421 | int res = -ENOTDIR; | 427 | int res = -ENOTDIR; | 
| 422 | if (!file->f_op || !file->f_op->readdir) | 428 | if (!file->f_op || !file->f_op->readdir) | 
| 423 | goto out; | 429 | goto out; | 
| 424 | down(&inode->i_sem); | 430 | down(&inode->i_sem); | 
| 425 | // down(&inode->i_zombie); | 431 | // down(&inode->i_zombie); | 
| 426 | res = -ENOENT; | 432 | res = -ENOENT; | 
| 427 | if (!IS_DEADDIR(inode)) { | 433 | if (!IS_DEADDIR(inode)) { | 
| 428 | lock_kernel(); | 434 | lock_kernel(); | 
| 429 | res = __xattr_readdir(file, buf, filler); | 435 | res = __xattr_readdir(file, buf, filler); | 
| 430 | unlock_kernel(); | 436 | unlock_kernel(); | 
| 431 | } | 437 | } | 
| 432 | // up(&inode->i_zombie); | 438 | // up(&inode->i_zombie); | 
| 433 | up(&inode->i_sem); | 439 | up(&inode->i_sem); | 
| 434 | out: | 440 | out: | 
| 435 | return res; | 441 | return res; | 
| 436 | } | 442 | } | 
| 437 | 443 | ||
| 438 | |||
| 439 | /* Internal operations on file data */ | 444 | /* Internal operations on file data */ | 
| 440 | static inline void | 445 | static inline void reiserfs_put_page(struct page *page) | 
| 441 | reiserfs_put_page(struct page *page) | ||
| 442 | { | 446 | { | 
| 443 | kunmap(page); | 447 | kunmap(page); | 
| 444 | page_cache_release(page); | 448 | page_cache_release(page); | 
| 445 | } | 449 | } | 
| 446 | 450 | ||
| 447 | static struct page * | 451 | static struct page *reiserfs_get_page(struct inode *dir, unsigned long n) | 
| 448 | reiserfs_get_page(struct inode *dir, unsigned long n) | ||
| 449 | { | 452 | { | 
| 450 | struct address_space *mapping = dir->i_mapping; | 453 | struct address_space *mapping = dir->i_mapping; | 
| 451 | struct page *page; | 454 | struct page *page; | 
| 452 | /* We can deadlock if we try to free dentries, | 455 | /* We can deadlock if we try to free dentries, | 
| 453 | and an unlink/rmdir has just occured - GFP_NOFS avoids this */ | 456 | and an unlink/rmdir has just occured - GFP_NOFS avoids this */ | 
| 454 | mapping->flags = (mapping->flags & ~__GFP_BITS_MASK) | GFP_NOFS; | 457 | mapping->flags = (mapping->flags & ~__GFP_BITS_MASK) | GFP_NOFS; | 
| 455 | page = read_cache_page (mapping, n, | 458 | page = read_cache_page(mapping, n, | 
| 456 | (filler_t*)mapping->a_ops->readpage, NULL); | 459 | (filler_t *) mapping->a_ops->readpage, NULL); | 
| 457 | if (!IS_ERR(page)) { | 460 | if (!IS_ERR(page)) { | 
| 458 | wait_on_page_locked(page); | 461 | wait_on_page_locked(page); | 
| 459 | kmap(page); | 462 | kmap(page); | 
| 460 | if (!PageUptodate(page)) | 463 | if (!PageUptodate(page)) | 
| 461 | goto fail; | 464 | goto fail; | 
| 462 | 465 | ||
| 463 | if (PageError(page)) | 466 | if (PageError(page)) | 
| 464 | goto fail; | 467 | goto fail; | 
| 465 | } | 468 | } | 
| 466 | return page; | 469 | return page; | 
| 467 | 470 | ||
| 468 | fail: | 471 | fail: | 
| 469 | reiserfs_put_page(page); | 472 | reiserfs_put_page(page); | 
| 470 | return ERR_PTR(-EIO); | 473 | return ERR_PTR(-EIO); | 
| 471 | } | 474 | } | 
| 472 | 475 | ||
| 473 | static inline __u32 | 476 | static inline __u32 xattr_hash(const char *msg, int len) | 
| 474 | xattr_hash (const char *msg, int len) | ||
| 475 | { | 477 | { | 
| 476 | return csum_partial (msg, len, 0); | 478 | return csum_partial(msg, len, 0); | 
| 477 | } | 479 | } | 
| 478 | 480 | ||
| 479 | /* Generic extended attribute operations that can be used by xa plugins */ | 481 | /* Generic extended attribute operations that can be used by xa plugins */ | 
| @@ -482,294 +484,300 @@ xattr_hash (const char *msg, int len) | |||
| 482 | * inode->i_sem: down | 484 | * inode->i_sem: down | 
| 483 | */ | 485 | */ | 
| 484 | int | 486 | int | 
| 485 | reiserfs_xattr_set (struct inode *inode, const char *name, const void *buffer, | 487 | reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, | 
| 486 | size_t buffer_size, int flags) | 488 | size_t buffer_size, int flags) | 
| 487 | { | 489 | { | 
| 488 | int err = 0; | 490 | int err = 0; | 
| 489 | struct file *fp; | 491 | struct file *fp; | 
| 490 | struct page *page; | 492 | struct page *page; | 
| 491 | char *data; | 493 | char *data; | 
| 492 | struct address_space *mapping; | 494 | struct address_space *mapping; | 
| 493 | size_t file_pos = 0; | 495 | size_t file_pos = 0; | 
| 494 | size_t buffer_pos = 0; | 496 | size_t buffer_pos = 0; | 
| 495 | struct inode *xinode; | 497 | struct inode *xinode; | 
| 496 | struct iattr newattrs; | 498 | struct iattr newattrs; | 
| 497 | __u32 xahash = 0; | 499 | __u32 xahash = 0; | 
| 498 | 500 | ||
| 499 | if (IS_RDONLY (inode)) | 501 | if (IS_RDONLY(inode)) | 
| 500 | return -EROFS; | 502 | return -EROFS; | 
| 501 | 503 | ||
| 502 | if (IS_IMMUTABLE (inode) || IS_APPEND (inode)) | 504 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | 
| 503 | return -EPERM; | 505 | return -EPERM; | 
| 504 | 506 | ||
| 505 | if (get_inode_sd_version (inode) == STAT_DATA_V1) | 507 | if (get_inode_sd_version(inode) == STAT_DATA_V1) | 
| 506 | return -EOPNOTSUPP; | 508 | return -EOPNOTSUPP; | 
| 507 | 509 | ||
| 508 | /* Empty xattrs are ok, they're just empty files, no hash */ | 510 | /* Empty xattrs are ok, they're just empty files, no hash */ | 
| 509 | if (buffer && buffer_size) | 511 | if (buffer && buffer_size) | 
| 510 | xahash = xattr_hash (buffer, buffer_size); | 512 | xahash = xattr_hash(buffer, buffer_size); | 
| 511 | 513 | ||
| 512 | open_file: | 514 | open_file: | 
| 513 | fp = open_xa_file (inode, name, flags); | 515 | fp = open_xa_file(inode, name, flags); | 
| 514 | if (IS_ERR (fp)) { | 516 | if (IS_ERR(fp)) { | 
| 515 | err = PTR_ERR (fp); | 517 | err = PTR_ERR(fp); | 
| 516 | goto out; | 518 | goto out; | 
| 517 | } | 519 | } | 
| 518 | 520 | ||
| 519 | xinode = fp->f_dentry->d_inode; | 521 | xinode = fp->f_dentry->d_inode; | 
| 520 | REISERFS_I(inode)->i_flags |= i_has_xattr_dir; | 522 | REISERFS_I(inode)->i_flags |= i_has_xattr_dir; | 
| 521 | 523 | ||
| 522 | /* we need to copy it off.. */ | 524 | /* we need to copy it off.. */ | 
| 523 | if (xinode->i_nlink > 1) { | 525 | if (xinode->i_nlink > 1) { | 
| 524 | fput(fp); | 526 | fput(fp); | 
| 525 | err = reiserfs_xattr_del (inode, name); | 527 | err = reiserfs_xattr_del(inode, name); | 
| 526 | if (err < 0) | 528 | if (err < 0) | 
| 527 | goto out; | 529 | goto out; | 
| 528 | /* We just killed the old one, we're not replacing anymore */ | 530 | /* We just killed the old one, we're not replacing anymore */ | 
| 529 | if (flags & XATTR_REPLACE) | 531 | if (flags & XATTR_REPLACE) | 
| 530 | flags &= ~XATTR_REPLACE; | 532 | flags &= ~XATTR_REPLACE; | 
| 531 | goto open_file; | 533 | goto open_file; | 
| 532 | } | 534 | } | 
| 533 | 535 | ||
| 534 | /* Resize it so we're ok to write there */ | 536 | /* Resize it so we're ok to write there */ | 
| 535 | newattrs.ia_size = buffer_size; | 537 | newattrs.ia_size = buffer_size; | 
| 536 | newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; | 538 | newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; | 
| 537 | down (&xinode->i_sem); | 539 | down(&xinode->i_sem); | 
| 538 | err = notify_change(fp->f_dentry, &newattrs); | 540 | err = notify_change(fp->f_dentry, &newattrs); | 
| 539 | if (err) | 541 | if (err) | 
| 540 | goto out_filp; | 542 | goto out_filp; | 
| 541 | 543 | ||
| 542 | mapping = xinode->i_mapping; | 544 | mapping = xinode->i_mapping; | 
| 543 | while (buffer_pos < buffer_size || buffer_pos == 0) { | 545 | while (buffer_pos < buffer_size || buffer_pos == 0) { | 
| 544 | size_t chunk; | 546 | size_t chunk; | 
| 545 | size_t skip = 0; | 547 | size_t skip = 0; | 
| 546 | size_t page_offset = (file_pos & (PAGE_CACHE_SIZE - 1)); | 548 | size_t page_offset = (file_pos & (PAGE_CACHE_SIZE - 1)); | 
| 547 | if (buffer_size - buffer_pos > PAGE_CACHE_SIZE) | 549 | if (buffer_size - buffer_pos > PAGE_CACHE_SIZE) | 
| 548 | chunk = PAGE_CACHE_SIZE; | 550 | chunk = PAGE_CACHE_SIZE; | 
| 549 | else | 551 | else | 
| 550 | chunk = buffer_size - buffer_pos; | 552 | chunk = buffer_size - buffer_pos; | 
| 551 | 553 | ||
| 552 | page = reiserfs_get_page (xinode, file_pos >> PAGE_CACHE_SHIFT); | 554 | page = reiserfs_get_page(xinode, file_pos >> PAGE_CACHE_SHIFT); | 
| 553 | if (IS_ERR (page)) { | 555 | if (IS_ERR(page)) { | 
| 554 | err = PTR_ERR (page); | 556 | err = PTR_ERR(page); | 
| 555 | goto out_filp; | 557 | goto out_filp; | 
| 556 | } | 558 | } | 
| 557 | 559 | ||
| 558 | lock_page (page); | 560 | lock_page(page); | 
| 559 | data = page_address (page); | 561 | data = page_address(page); | 
| 560 | 562 | ||
| 561 | if (file_pos == 0) { | 563 | if (file_pos == 0) { | 
| 562 | struct reiserfs_xattr_header *rxh; | 564 | struct reiserfs_xattr_header *rxh; | 
| 563 | skip = file_pos = sizeof (struct reiserfs_xattr_header); | 565 | skip = file_pos = sizeof(struct reiserfs_xattr_header); | 
| 564 | if (chunk + skip > PAGE_CACHE_SIZE) | 566 | if (chunk + skip > PAGE_CACHE_SIZE) | 
| 565 | chunk = PAGE_CACHE_SIZE - skip; | 567 | chunk = PAGE_CACHE_SIZE - skip; | 
| 566 | rxh = (struct reiserfs_xattr_header *)data; | 568 | rxh = (struct reiserfs_xattr_header *)data; | 
| 567 | rxh->h_magic = cpu_to_le32 (REISERFS_XATTR_MAGIC); | 569 | rxh->h_magic = cpu_to_le32(REISERFS_XATTR_MAGIC); | 
| 568 | rxh->h_hash = cpu_to_le32 (xahash); | 570 | rxh->h_hash = cpu_to_le32(xahash); | 
| 569 | } | 571 | } | 
| 570 | 572 | ||
| 571 | err = mapping->a_ops->prepare_write (fp, page, page_offset, | 573 | err = mapping->a_ops->prepare_write(fp, page, page_offset, | 
| 572 | page_offset + chunk + skip); | 574 | page_offset + chunk + skip); | 
| 573 | if (!err) { | 575 | if (!err) { | 
| 574 | if (buffer) | 576 | if (buffer) | 
| 575 | memcpy (data + skip, buffer + buffer_pos, chunk); | 577 | memcpy(data + skip, buffer + buffer_pos, chunk); | 
| 576 | err = mapping->a_ops->commit_write (fp, page, page_offset, | 578 | err = | 
| 577 | page_offset + chunk + skip); | 579 | mapping->a_ops->commit_write(fp, page, page_offset, | 
| 580 | page_offset + chunk + | ||
| 581 | skip); | ||
| 582 | } | ||
| 583 | unlock_page(page); | ||
| 584 | reiserfs_put_page(page); | ||
| 585 | buffer_pos += chunk; | ||
| 586 | file_pos += chunk; | ||
| 587 | skip = 0; | ||
| 588 | if (err || buffer_size == 0 || !buffer) | ||
| 589 | break; | ||
| 590 | } | ||
| 591 | |||
| 592 | /* We can't mark the inode dirty if it's not hashed. This is the case | ||
| 593 | * when we're inheriting the default ACL. If we dirty it, the inode | ||
| 594 | * gets marked dirty, but won't (ever) make it onto the dirty list until | ||
| 595 | * it's synced explicitly to clear I_DIRTY. This is bad. */ | ||
| 596 | if (!hlist_unhashed(&inode->i_hash)) { | ||
| 597 | inode->i_ctime = CURRENT_TIME_SEC; | ||
| 598 | mark_inode_dirty(inode); | ||
| 578 | } | 599 | } | 
| 579 | unlock_page (page); | 600 | |
| 580 | reiserfs_put_page (page); | 601 | out_filp: | 
| 581 | buffer_pos += chunk; | 602 | up(&xinode->i_sem); | 
| 582 | file_pos += chunk; | 603 | fput(fp); | 
| 583 | skip = 0; | 604 | |
| 584 | if (err || buffer_size == 0 || !buffer) | 605 | out: | 
| 585 | break; | 606 | return err; | 
| 586 | } | ||
| 587 | |||
| 588 | /* We can't mark the inode dirty if it's not hashed. This is the case | ||
| 589 | * when we're inheriting the default ACL. If we dirty it, the inode | ||
| 590 | * gets marked dirty, but won't (ever) make it onto the dirty list until | ||
| 591 | * it's synced explicitly to clear I_DIRTY. This is bad. */ | ||
| 592 | if (!hlist_unhashed(&inode->i_hash)) { | ||
| 593 | inode->i_ctime = CURRENT_TIME_SEC; | ||
| 594 | mark_inode_dirty (inode); | ||
| 595 | } | ||
| 596 | |||
| 597 | out_filp: | ||
| 598 | up (&xinode->i_sem); | ||
| 599 | fput(fp); | ||
| 600 | |||
| 601 | out: | ||
| 602 | return err; | ||
| 603 | } | 607 | } | 
| 604 | 608 | ||
| 605 | /* | 609 | /* | 
| 606 | * inode->i_sem: down | 610 | * inode->i_sem: down | 
| 607 | */ | 611 | */ | 
| 608 | int | 612 | int | 
| 609 | reiserfs_xattr_get (const struct inode *inode, const char *name, void *buffer, | 613 | reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer, | 
| 610 | size_t buffer_size) | 614 | size_t buffer_size) | 
| 611 | { | 615 | { | 
| 612 | ssize_t err = 0; | 616 | ssize_t err = 0; | 
| 613 | struct file *fp; | 617 | struct file *fp; | 
| 614 | size_t isize; | 618 | size_t isize; | 
| 615 | size_t file_pos = 0; | 619 | size_t file_pos = 0; | 
| 616 | size_t buffer_pos = 0; | 620 | size_t buffer_pos = 0; | 
| 617 | struct page *page; | 621 | struct page *page; | 
| 618 | struct inode *xinode; | 622 | struct inode *xinode; | 
| 619 | __u32 hash = 0; | 623 | __u32 hash = 0; | 
| 620 | 624 | ||
| 621 | if (name == NULL) | 625 | if (name == NULL) | 
| 622 | return -EINVAL; | 626 | return -EINVAL; | 
| 623 | 627 | ||
| 624 | /* We can't have xattrs attached to v1 items since they don't have | 628 | /* We can't have xattrs attached to v1 items since they don't have | 
| 625 | * generation numbers */ | 629 | * generation numbers */ | 
| 626 | if (get_inode_sd_version (inode) == STAT_DATA_V1) | 630 | if (get_inode_sd_version(inode) == STAT_DATA_V1) | 
| 627 | return -EOPNOTSUPP; | 631 | return -EOPNOTSUPP; | 
| 628 | 632 | ||
| 629 | fp = open_xa_file (inode, name, FL_READONLY); | 633 | fp = open_xa_file(inode, name, FL_READONLY); | 
| 630 | if (IS_ERR (fp)) { | 634 | if (IS_ERR(fp)) { | 
| 631 | err = PTR_ERR (fp); | 635 | err = PTR_ERR(fp); | 
| 632 | goto out; | 636 | goto out; | 
| 633 | } | 637 | } | 
| 634 | 638 | ||
| 635 | xinode = fp->f_dentry->d_inode; | 639 | xinode = fp->f_dentry->d_inode; | 
| 636 | isize = xinode->i_size; | 640 | isize = xinode->i_size; | 
| 637 | REISERFS_I(inode)->i_flags |= i_has_xattr_dir; | 641 | REISERFS_I(inode)->i_flags |= i_has_xattr_dir; | 
| 638 | 642 | ||
| 639 | /* Just return the size needed */ | 643 | /* Just return the size needed */ | 
| 640 | if (buffer == NULL) { | 644 | if (buffer == NULL) { | 
| 641 | err = isize - sizeof (struct reiserfs_xattr_header); | 645 | err = isize - sizeof(struct reiserfs_xattr_header); | 
| 642 | goto out_dput; | 646 | goto out_dput; | 
| 643 | } | 647 | } | 
| 644 | 648 | ||
| 645 | if (buffer_size < isize - sizeof (struct reiserfs_xattr_header)) { | 649 | if (buffer_size < isize - sizeof(struct reiserfs_xattr_header)) { | 
| 646 | err = -ERANGE; | 650 | err = -ERANGE; | 
| 647 | goto out_dput; | 651 | goto out_dput; | 
| 648 | } | 652 | } | 
| 649 | 653 | ||
| 650 | while (file_pos < isize) { | 654 | while (file_pos < isize) { | 
| 651 | size_t chunk; | 655 | size_t chunk; | 
| 652 | char *data; | 656 | char *data; | 
| 653 | size_t skip = 0; | 657 | size_t skip = 0; | 
| 654 | if (isize - file_pos > PAGE_CACHE_SIZE) | 658 | if (isize - file_pos > PAGE_CACHE_SIZE) | 
| 655 | chunk = PAGE_CACHE_SIZE; | 659 | chunk = PAGE_CACHE_SIZE; | 
| 656 | else | 660 | else | 
| 657 | chunk = isize - file_pos; | 661 | chunk = isize - file_pos; | 
| 658 | 662 | ||
| 659 | page = reiserfs_get_page (xinode, file_pos >> PAGE_CACHE_SHIFT); | 663 | page = reiserfs_get_page(xinode, file_pos >> PAGE_CACHE_SHIFT); | 
| 660 | if (IS_ERR (page)) { | 664 | if (IS_ERR(page)) { | 
| 661 | err = PTR_ERR (page); | 665 | err = PTR_ERR(page); | 
| 662 | goto out_dput; | 666 | goto out_dput; | 
| 663 | } | 667 | } | 
| 664 | 668 | ||
| 665 | lock_page (page); | 669 | lock_page(page); | 
| 666 | data = page_address (page); | 670 | data = page_address(page); | 
| 667 | if (file_pos == 0) { | 671 | if (file_pos == 0) { | 
| 668 | struct reiserfs_xattr_header *rxh = | 672 | struct reiserfs_xattr_header *rxh = | 
| 669 | (struct reiserfs_xattr_header *)data; | 673 | (struct reiserfs_xattr_header *)data; | 
| 670 | skip = file_pos = sizeof (struct reiserfs_xattr_header); | 674 | skip = file_pos = sizeof(struct reiserfs_xattr_header); | 
| 671 | chunk -= skip; | 675 | chunk -= skip; | 
| 672 | /* Magic doesn't match up.. */ | 676 | /* Magic doesn't match up.. */ | 
| 673 | if (rxh->h_magic != cpu_to_le32 (REISERFS_XATTR_MAGIC)) { | 677 | if (rxh->h_magic != cpu_to_le32(REISERFS_XATTR_MAGIC)) { | 
| 674 | unlock_page (page); | 678 | unlock_page(page); | 
| 675 | reiserfs_put_page (page); | 679 | reiserfs_put_page(page); | 
| 676 | reiserfs_warning (inode->i_sb, "Invalid magic for xattr (%s) " | 680 | reiserfs_warning(inode->i_sb, | 
| 677 | "associated with %k", name, | 681 | "Invalid magic for xattr (%s) " | 
| 678 | INODE_PKEY (inode)); | 682 | "associated with %k", name, | 
| 679 | err = -EIO; | 683 | INODE_PKEY(inode)); | 
| 680 | goto out_dput; | 684 | err = -EIO; | 
| 681 | } | 685 | goto out_dput; | 
| 682 | hash = le32_to_cpu (rxh->h_hash); | 686 | } | 
| 683 | } | 687 | hash = le32_to_cpu(rxh->h_hash); | 
| 684 | memcpy (buffer + buffer_pos, data + skip, chunk); | 688 | } | 
| 685 | unlock_page (page); | 689 | memcpy(buffer + buffer_pos, data + skip, chunk); | 
| 686 | reiserfs_put_page (page); | 690 | unlock_page(page); | 
| 687 | file_pos += chunk; | 691 | reiserfs_put_page(page); | 
| 688 | buffer_pos += chunk; | 692 | file_pos += chunk; | 
| 689 | skip = 0; | 693 | buffer_pos += chunk; | 
| 690 | } | 694 | skip = 0; | 
| 691 | err = isize - sizeof (struct reiserfs_xattr_header); | 695 | } | 
| 692 | 696 | err = isize - sizeof(struct reiserfs_xattr_header); | |
| 693 | if (xattr_hash (buffer, isize - sizeof (struct reiserfs_xattr_header)) != hash) { | 697 | |
| 694 | reiserfs_warning (inode->i_sb, "Invalid hash for xattr (%s) associated " | 698 | if (xattr_hash(buffer, isize - sizeof(struct reiserfs_xattr_header)) != | 
| 695 | "with %k", name, INODE_PKEY (inode)); | 699 | hash) { | 
| 696 | err = -EIO; | 700 | reiserfs_warning(inode->i_sb, | 
| 697 | } | 701 | "Invalid hash for xattr (%s) associated " | 
| 698 | 702 | "with %k", name, INODE_PKEY(inode)); | |
| 699 | out_dput: | 703 | err = -EIO; | 
| 700 | fput(fp); | 704 | } | 
| 701 | 705 | ||
| 702 | out: | 706 | out_dput: | 
| 703 | return err; | 707 | fput(fp); | 
| 708 | |||
| 709 | out: | ||
| 710 | return err; | ||
| 704 | } | 711 | } | 
| 705 | 712 | ||
| 706 | static int | 713 | static int | 
| 707 | __reiserfs_xattr_del (struct dentry *xadir, const char *name, int namelen) | 714 | __reiserfs_xattr_del(struct dentry *xadir, const char *name, int namelen) | 
| 708 | { | 715 | { | 
| 709 | struct dentry *dentry; | 716 | struct dentry *dentry; | 
| 710 | struct inode *dir = xadir->d_inode; | 717 | struct inode *dir = xadir->d_inode; | 
| 711 | int err = 0; | 718 | int err = 0; | 
| 712 | 719 | ||
| 713 | dentry = lookup_one_len (name, xadir, namelen); | 720 | dentry = lookup_one_len(name, xadir, namelen); | 
| 714 | if (IS_ERR (dentry)) { | 721 | if (IS_ERR(dentry)) { | 
| 715 | err = PTR_ERR (dentry); | 722 | err = PTR_ERR(dentry); | 
| 716 | goto out; | 723 | goto out; | 
| 717 | } else if (!dentry->d_inode) { | 724 | } else if (!dentry->d_inode) { | 
| 718 | err = -ENODATA; | 725 | err = -ENODATA; | 
| 719 | goto out_file; | 726 | goto out_file; | 
| 720 | } | 727 | } | 
| 721 | 728 | ||
| 722 | /* Skip directories.. */ | 729 | /* Skip directories.. */ | 
| 723 | if (S_ISDIR (dentry->d_inode->i_mode)) | 730 | if (S_ISDIR(dentry->d_inode->i_mode)) | 
| 724 | goto out_file; | 731 | goto out_file; | 
| 725 | 732 | ||
| 726 | if (!is_reiserfs_priv_object (dentry->d_inode)) { | 733 | if (!is_reiserfs_priv_object(dentry->d_inode)) { | 
| 727 | reiserfs_warning (dir->i_sb, "OID %08x [%.*s/%.*s] doesn't have " | 734 | reiserfs_warning(dir->i_sb, "OID %08x [%.*s/%.*s] doesn't have " | 
| 728 | "priv flag set [parent is %sset].", | 735 | "priv flag set [parent is %sset].", | 
| 729 | le32_to_cpu (INODE_PKEY (dentry->d_inode)->k_objectid), | 736 | le32_to_cpu(INODE_PKEY(dentry->d_inode)-> | 
| 730 | xadir->d_name.len, xadir->d_name.name, namelen, name, | 737 | k_objectid), xadir->d_name.len, | 
| 731 | is_reiserfs_priv_object (xadir->d_inode) ? "" : "not "); | 738 | xadir->d_name.name, namelen, name, | 
| 732 | dput (dentry); | 739 | is_reiserfs_priv_object(xadir-> | 
| 733 | return -EIO; | 740 | d_inode) ? "" : | 
| 734 | } | 741 | "not "); | 
| 735 | 742 | dput(dentry); | |
| 736 | err = dir->i_op->unlink (dir, dentry); | 743 | return -EIO; | 
| 737 | if (!err) | 744 | } | 
| 738 | d_delete (dentry); | ||
| 739 | |||
| 740 | out_file: | ||
| 741 | dput (dentry); | ||
| 742 | |||
| 743 | out: | ||
| 744 | return err; | ||
| 745 | } | ||
| 746 | 745 | ||
| 746 | err = dir->i_op->unlink(dir, dentry); | ||
| 747 | if (!err) | ||
| 748 | d_delete(dentry); | ||
| 747 | 749 | ||
| 748 | int | 750 | out_file: | 
| 749 | reiserfs_xattr_del (struct inode *inode, const char *name) | 751 | dput(dentry); | 
| 752 | |||
| 753 | out: | ||
| 754 | return err; | ||
| 755 | } | ||
| 756 | |||
| 757 | int reiserfs_xattr_del(struct inode *inode, const char *name) | ||
| 750 | { | 758 | { | 
| 751 | struct dentry *dir; | 759 | struct dentry *dir; | 
| 752 | int err; | 760 | int err; | 
| 753 | 761 | ||
| 754 | if (IS_RDONLY (inode)) | 762 | if (IS_RDONLY(inode)) | 
| 755 | return -EROFS; | 763 | return -EROFS; | 
| 756 | 764 | ||
| 757 | dir = open_xa_dir (inode, FL_READONLY); | 765 | dir = open_xa_dir(inode, FL_READONLY); | 
| 758 | if (IS_ERR (dir)) { | 766 | if (IS_ERR(dir)) { | 
| 759 | err = PTR_ERR (dir); | 767 | err = PTR_ERR(dir); | 
| 760 | goto out; | 768 | goto out; | 
| 761 | } | 769 | } | 
| 762 | 770 | ||
| 763 | err = __reiserfs_xattr_del (dir, name, strlen (name)); | 771 | err = __reiserfs_xattr_del(dir, name, strlen(name)); | 
| 764 | dput (dir); | 772 | dput(dir); | 
| 765 | 773 | ||
| 766 | if (!err) { | 774 | if (!err) { | 
| 767 | inode->i_ctime = CURRENT_TIME_SEC; | 775 | inode->i_ctime = CURRENT_TIME_SEC; | 
| 768 | mark_inode_dirty (inode); | 776 | mark_inode_dirty(inode); | 
| 769 | } | 777 | } | 
| 770 | 778 | ||
| 771 | out: | 779 | out: | 
| 772 | return err; | 780 | return err; | 
| 773 | } | 781 | } | 
| 774 | 782 | ||
| 775 | /* The following are side effects of other operations that aren't explicitly | 783 | /* The following are side effects of other operations that aren't explicitly | 
| @@ -777,167 +785,163 @@ out: | |||
| 777 | * or ownership changes, object deletions, etc. */ | 785 | * or ownership changes, object deletions, etc. */ | 
| 778 | 786 | ||
| 779 | static int | 787 | static int | 
| 780 | reiserfs_delete_xattrs_filler (void *buf, const char *name, int namelen, | 788 | reiserfs_delete_xattrs_filler(void *buf, const char *name, int namelen, | 
| 781 | loff_t offset, ino_t ino, unsigned int d_type) | 789 | loff_t offset, ino_t ino, unsigned int d_type) | 
| 782 | { | 790 | { | 
| 783 | struct dentry *xadir = (struct dentry *)buf; | 791 | struct dentry *xadir = (struct dentry *)buf; | 
| 784 | 792 | ||
| 785 | return __reiserfs_xattr_del (xadir, name, namelen); | 793 | return __reiserfs_xattr_del(xadir, name, namelen); | 
| 786 | 794 | ||
| 787 | } | 795 | } | 
| 788 | 796 | ||
| 789 | /* This is called w/ inode->i_sem downed */ | 797 | /* This is called w/ inode->i_sem downed */ | 
| 790 | int | 798 | int reiserfs_delete_xattrs(struct inode *inode) | 
| 791 | reiserfs_delete_xattrs (struct inode *inode) | ||
| 792 | { | 799 | { | 
| 793 | struct file *fp; | 800 | struct file *fp; | 
| 794 | struct dentry *dir, *root; | 801 | struct dentry *dir, *root; | 
| 795 | int err = 0; | 802 | int err = 0; | 
| 796 | 803 | ||
| 797 | /* Skip out, an xattr has no xattrs associated with it */ | 804 | /* Skip out, an xattr has no xattrs associated with it */ | 
| 798 | if (is_reiserfs_priv_object (inode) || | 805 | if (is_reiserfs_priv_object(inode) || | 
| 799 | get_inode_sd_version (inode) == STAT_DATA_V1 || | 806 | get_inode_sd_version(inode) == STAT_DATA_V1 || | 
| 800 | !reiserfs_xattrs(inode->i_sb)) | 807 | !reiserfs_xattrs(inode->i_sb)) { | 
| 801 | { | 808 | return 0; | 
| 802 | return 0; | 809 | } | 
| 803 | } | 810 | reiserfs_read_lock_xattrs(inode->i_sb); | 
| 804 | reiserfs_read_lock_xattrs (inode->i_sb); | 811 | dir = open_xa_dir(inode, FL_READONLY); | 
| 805 | dir = open_xa_dir (inode, FL_READONLY); | 812 | reiserfs_read_unlock_xattrs(inode->i_sb); | 
| 806 | reiserfs_read_unlock_xattrs (inode->i_sb); | 813 | if (IS_ERR(dir)) { | 
| 807 | if (IS_ERR (dir)) { | 814 | err = PTR_ERR(dir); | 
| 808 | err = PTR_ERR (dir); | 815 | goto out; | 
| 809 | goto out; | 816 | } else if (!dir->d_inode) { | 
| 810 | } else if (!dir->d_inode) { | 817 | dput(dir); | 
| 811 | dput (dir); | 818 | return 0; | 
| 812 | return 0; | 819 | } | 
| 813 | } | 820 | |
| 814 | 821 | fp = dentry_open(dir, NULL, O_RDWR); | |
| 815 | fp = dentry_open (dir, NULL, O_RDWR); | 822 | if (IS_ERR(fp)) { | 
| 816 | if (IS_ERR (fp)) { | 823 | err = PTR_ERR(fp); | 
| 817 | err = PTR_ERR (fp); | 824 | /* dentry_open dputs the dentry if it fails */ | 
| 818 | /* dentry_open dputs the dentry if it fails */ | 825 | goto out; | 
| 819 | goto out; | 826 | } | 
| 820 | } | 827 | |
| 821 | 828 | lock_kernel(); | |
| 822 | lock_kernel (); | 829 | err = xattr_readdir(fp, reiserfs_delete_xattrs_filler, dir); | 
| 823 | err = xattr_readdir (fp, reiserfs_delete_xattrs_filler, dir); | 830 | if (err) { | 
| 824 | if (err) { | 831 | unlock_kernel(); | 
| 825 | unlock_kernel (); | 832 | goto out_dir; | 
| 826 | goto out_dir; | 833 | } | 
| 827 | } | 834 | |
| 828 | 835 | /* Leftovers besides . and .. -- that's not good. */ | |
| 829 | /* Leftovers besides . and .. -- that's not good. */ | 836 | if (dir->d_inode->i_nlink <= 2) { | 
| 830 | if (dir->d_inode->i_nlink <= 2) { | 837 | root = get_xa_root(inode->i_sb); | 
| 831 | root = get_xa_root (inode->i_sb); | 838 | reiserfs_write_lock_xattrs(inode->i_sb); | 
| 832 | reiserfs_write_lock_xattrs (inode->i_sb); | 839 | err = vfs_rmdir(root->d_inode, dir); | 
| 833 | err = vfs_rmdir (root->d_inode, dir); | 840 | reiserfs_write_unlock_xattrs(inode->i_sb); | 
| 834 | reiserfs_write_unlock_xattrs (inode->i_sb); | 841 | dput(root); | 
| 835 | dput (root); | 842 | } else { | 
| 836 | } else { | 843 | reiserfs_warning(inode->i_sb, | 
| 837 | reiserfs_warning (inode->i_sb, | 844 | "Couldn't remove all entries in directory"); | 
| 838 | "Couldn't remove all entries in directory"); | 845 | } | 
| 839 | } | 846 | unlock_kernel(); | 
| 840 | unlock_kernel (); | 847 | |
| 841 | 848 | out_dir: | |
| 842 | out_dir: | 849 | fput(fp); | 
| 843 | fput(fp); | 850 | |
| 844 | 851 | out: | |
| 845 | out: | 852 | if (!err) | 
| 846 | if (!err) | 853 | REISERFS_I(inode)->i_flags = | 
| 847 | REISERFS_I(inode)->i_flags = REISERFS_I(inode)->i_flags & ~i_has_xattr_dir; | 854 | REISERFS_I(inode)->i_flags & ~i_has_xattr_dir; | 
| 848 | return err; | 855 | return err; | 
| 849 | } | 856 | } | 
| 850 | 857 | ||
| 851 | struct reiserfs_chown_buf { | 858 | struct reiserfs_chown_buf { | 
| 852 | struct inode *inode; | 859 | struct inode *inode; | 
| 853 | struct dentry *xadir; | 860 | struct dentry *xadir; | 
| 854 | struct iattr *attrs; | 861 | struct iattr *attrs; | 
| 855 | }; | 862 | }; | 
| 856 | 863 | ||
| 857 | /* XXX: If there is a better way to do this, I'd love to hear about it */ | 864 | /* XXX: If there is a better way to do this, I'd love to hear about it */ | 
| 858 | static int | 865 | static int | 
| 859 | reiserfs_chown_xattrs_filler (void *buf, const char *name, int namelen, | 866 | reiserfs_chown_xattrs_filler(void *buf, const char *name, int namelen, | 
| 860 | loff_t offset, ino_t ino, unsigned int d_type) | 867 | loff_t offset, ino_t ino, unsigned int d_type) | 
| 861 | { | 868 | { | 
| 862 | struct reiserfs_chown_buf *chown_buf = (struct reiserfs_chown_buf *)buf; | 869 | struct reiserfs_chown_buf *chown_buf = (struct reiserfs_chown_buf *)buf; | 
| 863 | struct dentry *xafile, *xadir = chown_buf->xadir; | 870 | struct dentry *xafile, *xadir = chown_buf->xadir; | 
| 864 | struct iattr *attrs = chown_buf->attrs; | 871 | struct iattr *attrs = chown_buf->attrs; | 
| 865 | int err = 0; | 872 | int err = 0; | 
| 866 | 873 | ||
| 867 | xafile = lookup_one_len (name, xadir, namelen); | 874 | xafile = lookup_one_len(name, xadir, namelen); | 
| 868 | if (IS_ERR (xafile)) | 875 | if (IS_ERR(xafile)) | 
| 869 | return PTR_ERR (xafile); | 876 | return PTR_ERR(xafile); | 
| 870 | else if (!xafile->d_inode) { | 877 | else if (!xafile->d_inode) { | 
| 871 | dput (xafile); | 878 | dput(xafile); | 
| 872 | return -ENODATA; | 879 | return -ENODATA; | 
| 873 | } | 880 | } | 
| 874 | 881 | ||
| 875 | if (!S_ISDIR (xafile->d_inode->i_mode)) | 882 | if (!S_ISDIR(xafile->d_inode->i_mode)) | 
| 876 | err = notify_change (xafile, attrs); | 883 | err = notify_change(xafile, attrs); | 
| 877 | dput (xafile); | 884 | dput(xafile); | 
| 878 | 885 | ||
| 879 | return err; | 886 | return err; | 
| 880 | } | 887 | } | 
| 881 | 888 | ||
| 882 | int | 889 | int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs) | 
| 883 | reiserfs_chown_xattrs (struct inode *inode, struct iattr *attrs) | ||
| 884 | { | 890 | { | 
| 885 | struct file *fp; | 891 | struct file *fp; | 
| 886 | struct dentry *dir; | 892 | struct dentry *dir; | 
| 887 | int err = 0; | 893 | int err = 0; | 
| 888 | struct reiserfs_chown_buf buf; | 894 | struct reiserfs_chown_buf buf; | 
| 889 | unsigned int ia_valid = attrs->ia_valid; | 895 | unsigned int ia_valid = attrs->ia_valid; | 
| 890 | 896 | ||
| 891 | /* Skip out, an xattr has no xattrs associated with it */ | 897 | /* Skip out, an xattr has no xattrs associated with it */ | 
| 892 | if (is_reiserfs_priv_object (inode) || | 898 | if (is_reiserfs_priv_object(inode) || | 
| 893 | get_inode_sd_version (inode) == STAT_DATA_V1 || | 899 | get_inode_sd_version(inode) == STAT_DATA_V1 || | 
| 894 | !reiserfs_xattrs(inode->i_sb)) | 900 | !reiserfs_xattrs(inode->i_sb)) { | 
| 895 | { | 901 | return 0; | 
| 896 | return 0; | 902 | } | 
| 897 | } | 903 | reiserfs_read_lock_xattrs(inode->i_sb); | 
| 898 | reiserfs_read_lock_xattrs (inode->i_sb); | 904 | dir = open_xa_dir(inode, FL_READONLY); | 
| 899 | dir = open_xa_dir (inode, FL_READONLY); | 905 | reiserfs_read_unlock_xattrs(inode->i_sb); | 
| 900 | reiserfs_read_unlock_xattrs (inode->i_sb); | 906 | if (IS_ERR(dir)) { | 
| 901 | if (IS_ERR (dir)) { | 907 | if (PTR_ERR(dir) != -ENODATA) | 
| 902 | if (PTR_ERR (dir) != -ENODATA) | 908 | err = PTR_ERR(dir); | 
| 903 | err = PTR_ERR (dir); | 909 | goto out; | 
| 904 | goto out; | 910 | } else if (!dir->d_inode) { | 
| 905 | } else if (!dir->d_inode) { | 911 | dput(dir); | 
| 906 | dput (dir); | 912 | goto out; | 
| 907 | goto out; | 913 | } | 
| 908 | } | 914 | |
| 909 | 915 | fp = dentry_open(dir, NULL, O_RDWR); | |
| 910 | fp = dentry_open (dir, NULL, O_RDWR); | 916 | if (IS_ERR(fp)) { | 
| 911 | if (IS_ERR (fp)) { | 917 | err = PTR_ERR(fp); | 
| 912 | err = PTR_ERR (fp); | 918 | /* dentry_open dputs the dentry if it fails */ | 
| 913 | /* dentry_open dputs the dentry if it fails */ | 919 | goto out; | 
| 914 | goto out; | 920 | } | 
| 915 | } | ||
| 916 | |||
| 917 | lock_kernel (); | ||
| 918 | |||
| 919 | attrs->ia_valid &= (ATTR_UID | ATTR_GID | ATTR_CTIME); | ||
| 920 | buf.xadir = dir; | ||
| 921 | buf.attrs = attrs; | ||
| 922 | buf.inode = inode; | ||
| 923 | |||
| 924 | err = xattr_readdir (fp, reiserfs_chown_xattrs_filler, &buf); | ||
| 925 | if (err) { | ||
| 926 | unlock_kernel (); | ||
| 927 | goto out_dir; | ||
| 928 | } | ||
| 929 | |||
| 930 | err = notify_change (dir, attrs); | ||
| 931 | unlock_kernel (); | ||
| 932 | |||
| 933 | out_dir: | ||
| 934 | fput(fp); | ||
| 935 | |||
| 936 | out: | ||
| 937 | attrs->ia_valid = ia_valid; | ||
| 938 | return err; | ||
| 939 | } | ||
| 940 | 921 | ||
| 922 | lock_kernel(); | ||
| 923 | |||
| 924 | attrs->ia_valid &= (ATTR_UID | ATTR_GID | ATTR_CTIME); | ||
| 925 | buf.xadir = dir; | ||
| 926 | buf.attrs = attrs; | ||
| 927 | buf.inode = inode; | ||
| 928 | |||
| 929 | err = xattr_readdir(fp, reiserfs_chown_xattrs_filler, &buf); | ||
| 930 | if (err) { | ||
| 931 | unlock_kernel(); | ||
| 932 | goto out_dir; | ||
| 933 | } | ||
| 934 | |||
| 935 | err = notify_change(dir, attrs); | ||
| 936 | unlock_kernel(); | ||
| 937 | |||
| 938 | out_dir: | ||
| 939 | fput(fp); | ||
| 940 | |||
| 941 | out: | ||
| 942 | attrs->ia_valid = ia_valid; | ||
| 943 | return err; | ||
| 944 | } | ||
| 941 | 945 | ||
| 942 | /* Actual operations that are exported to VFS-land */ | 946 | /* Actual operations that are exported to VFS-land */ | 
| 943 | 947 | ||
| @@ -946,61 +950,60 @@ out: | |||
| 946 | * Preliminary locking: we down dentry->d_inode->i_sem | 950 | * Preliminary locking: we down dentry->d_inode->i_sem | 
| 947 | */ | 951 | */ | 
| 948 | ssize_t | 952 | ssize_t | 
| 949 | reiserfs_getxattr (struct dentry *dentry, const char *name, void *buffer, | 953 | reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer, | 
| 950 | size_t size) | 954 | size_t size) | 
| 951 | { | 955 | { | 
| 952 | struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name); | 956 | struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix(name); | 
| 953 | int err; | 957 | int err; | 
| 954 | 958 | ||
| 955 | if (!xah || !reiserfs_xattrs(dentry->d_sb) || | 959 | if (!xah || !reiserfs_xattrs(dentry->d_sb) || | 
| 956 | get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1) | 960 | get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) | 
| 957 | return -EOPNOTSUPP; | 961 | return -EOPNOTSUPP; | 
| 958 | 962 | ||
| 959 | reiserfs_read_lock_xattr_i (dentry->d_inode); | 963 | reiserfs_read_lock_xattr_i(dentry->d_inode); | 
| 960 | reiserfs_read_lock_xattrs (dentry->d_sb); | 964 | reiserfs_read_lock_xattrs(dentry->d_sb); | 
| 961 | err = xah->get (dentry->d_inode, name, buffer, size); | 965 | err = xah->get(dentry->d_inode, name, buffer, size); | 
| 962 | reiserfs_read_unlock_xattrs (dentry->d_sb); | 966 | reiserfs_read_unlock_xattrs(dentry->d_sb); | 
| 963 | reiserfs_read_unlock_xattr_i (dentry->d_inode); | 967 | reiserfs_read_unlock_xattr_i(dentry->d_inode); | 
| 964 | return err; | 968 | return err; | 
| 965 | } | 969 | } | 
| 966 | 970 | ||
| 967 | |||
| 968 | /* | 971 | /* | 
| 969 | * Inode operation setxattr() | 972 | * Inode operation setxattr() | 
| 970 | * | 973 | * | 
| 971 | * dentry->d_inode->i_sem down | 974 | * dentry->d_inode->i_sem down | 
| 972 | */ | 975 | */ | 
| 973 | int | 976 | int | 
| 974 | reiserfs_setxattr (struct dentry *dentry, const char *name, const void *value, | 977 | reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value, | 
| 975 | size_t size, int flags) | 978 | size_t size, int flags) | 
| 976 | { | 979 | { | 
| 977 | struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name); | 980 | struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix(name); | 
| 978 | int err; | 981 | int err; | 
| 979 | int lock; | 982 | int lock; | 
| 980 | 983 | ||
| 981 | if (!xah || !reiserfs_xattrs(dentry->d_sb) || | 984 | if (!xah || !reiserfs_xattrs(dentry->d_sb) || | 
| 982 | get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1) | 985 | get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) | 
| 983 | return -EOPNOTSUPP; | 986 | return -EOPNOTSUPP; | 
| 984 | 987 | ||
| 985 | if (IS_RDONLY (dentry->d_inode)) | 988 | if (IS_RDONLY(dentry->d_inode)) | 
| 986 | return -EROFS; | 989 | return -EROFS; | 
| 987 | 990 | ||
| 988 | if (IS_IMMUTABLE (dentry->d_inode) || IS_APPEND (dentry->d_inode)) | 991 | if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode)) | 
| 989 | return -EROFS; | 992 | return -EROFS; | 
| 990 | 993 | ||
| 991 | reiserfs_write_lock_xattr_i (dentry->d_inode); | 994 | reiserfs_write_lock_xattr_i(dentry->d_inode); | 
| 992 | lock = !has_xattr_dir (dentry->d_inode); | 995 | lock = !has_xattr_dir(dentry->d_inode); | 
| 993 | if (lock) | 996 | if (lock) | 
| 994 | reiserfs_write_lock_xattrs (dentry->d_sb); | 997 | reiserfs_write_lock_xattrs(dentry->d_sb); | 
| 995 | else | 998 | else | 
| 996 | reiserfs_read_lock_xattrs (dentry->d_sb); | 999 | reiserfs_read_lock_xattrs(dentry->d_sb); | 
| 997 | err = xah->set (dentry->d_inode, name, value, size, flags); | 1000 | err = xah->set(dentry->d_inode, name, value, size, flags); | 
| 998 | if (lock) | 1001 | if (lock) | 
| 999 | reiserfs_write_unlock_xattrs (dentry->d_sb); | 1002 | reiserfs_write_unlock_xattrs(dentry->d_sb); | 
| 1000 | else | 1003 | else | 
| 1001 | reiserfs_read_unlock_xattrs (dentry->d_sb); | 1004 | reiserfs_read_unlock_xattrs(dentry->d_sb); | 
| 1002 | reiserfs_write_unlock_xattr_i (dentry->d_inode); | 1005 | reiserfs_write_unlock_xattr_i(dentry->d_inode); | 
| 1003 | return err; | 1006 | return err; | 
| 1004 | } | 1007 | } | 
| 1005 | 1008 | ||
| 1006 | /* | 1009 | /* | 
| @@ -1008,344 +1011,343 @@ reiserfs_setxattr (struct dentry *dentry, const char *name, const void *value, | |||
| 1008 | * | 1011 | * | 
| 1009 | * dentry->d_inode->i_sem down | 1012 | * dentry->d_inode->i_sem down | 
| 1010 | */ | 1013 | */ | 
| 1011 | int | 1014 | int reiserfs_removexattr(struct dentry *dentry, const char *name) | 
| 1012 | reiserfs_removexattr (struct dentry *dentry, const char *name) | ||
| 1013 | { | 1015 | { | 
| 1014 | int err; | 1016 | int err; | 
| 1015 | struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name); | 1017 | struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix(name); | 
| 1016 | 1018 | ||
| 1017 | if (!xah || !reiserfs_xattrs(dentry->d_sb) || | 1019 | if (!xah || !reiserfs_xattrs(dentry->d_sb) || | 
| 1018 | get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1) | 1020 | get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) | 
| 1019 | return -EOPNOTSUPP; | 1021 | return -EOPNOTSUPP; | 
| 1020 | 1022 | ||
| 1021 | if (IS_RDONLY (dentry->d_inode)) | 1023 | if (IS_RDONLY(dentry->d_inode)) | 
| 1022 | return -EROFS; | 1024 | return -EROFS; | 
| 1023 | 1025 | ||
| 1024 | if (IS_IMMUTABLE (dentry->d_inode) || IS_APPEND (dentry->d_inode)) | 1026 | if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode)) | 
| 1025 | return -EPERM; | 1027 | return -EPERM; | 
| 1026 | 1028 | ||
| 1027 | reiserfs_write_lock_xattr_i (dentry->d_inode); | 1029 | reiserfs_write_lock_xattr_i(dentry->d_inode); | 
| 1028 | reiserfs_read_lock_xattrs (dentry->d_sb); | 1030 | reiserfs_read_lock_xattrs(dentry->d_sb); | 
| 1029 | 1031 | ||
| 1030 | /* Deletion pre-operation */ | 1032 | /* Deletion pre-operation */ | 
| 1031 | if (xah->del) { | 1033 | if (xah->del) { | 
| 1032 | err = xah->del (dentry->d_inode, name); | 1034 | err = xah->del(dentry->d_inode, name); | 
| 1033 | if (err) | 1035 | if (err) | 
| 1034 | goto out; | 1036 | goto out; | 
| 1035 | } | 1037 | } | 
| 1036 | 1038 | ||
| 1037 | err = reiserfs_xattr_del (dentry->d_inode, name); | 1039 | err = reiserfs_xattr_del(dentry->d_inode, name); | 
| 1038 | 1040 | ||
| 1039 | dentry->d_inode->i_ctime = CURRENT_TIME_SEC; | 1041 | dentry->d_inode->i_ctime = CURRENT_TIME_SEC; | 
| 1040 | mark_inode_dirty (dentry->d_inode); | 1042 | mark_inode_dirty(dentry->d_inode); | 
| 1041 | 1043 | ||
| 1042 | out: | 1044 | out: | 
| 1043 | reiserfs_read_unlock_xattrs (dentry->d_sb); | 1045 | reiserfs_read_unlock_xattrs(dentry->d_sb); | 
| 1044 | reiserfs_write_unlock_xattr_i (dentry->d_inode); | 1046 | reiserfs_write_unlock_xattr_i(dentry->d_inode); | 
| 1045 | return err; | 1047 | return err; | 
| 1046 | } | 1048 | } | 
| 1047 | 1049 | ||
| 1048 | |||
| 1049 | /* This is what filldir will use: | 1050 | /* This is what filldir will use: | 
| 1050 | * r_pos will always contain the amount of space required for the entire | 1051 | * r_pos will always contain the amount of space required for the entire | 
| 1051 | * list. If r_pos becomes larger than r_size, we need more space and we | 1052 | * list. If r_pos becomes larger than r_size, we need more space and we | 
| 1052 | * return an error indicating this. If r_pos is less than r_size, then we've | 1053 | * return an error indicating this. If r_pos is less than r_size, then we've | 
| 1053 | * filled the buffer successfully and we return success */ | 1054 | * filled the buffer successfully and we return success */ | 
| 1054 | struct reiserfs_listxattr_buf { | 1055 | struct reiserfs_listxattr_buf { | 
| 1055 | int r_pos; | 1056 | int r_pos; | 
| 1056 | int r_size; | 1057 | int r_size; | 
| 1057 | char *r_buf; | 1058 | char *r_buf; | 
| 1058 | struct inode *r_inode; | 1059 | struct inode *r_inode; | 
| 1059 | }; | 1060 | }; | 
| 1060 | 1061 | ||
| 1061 | static int | 1062 | static int | 
| 1062 | reiserfs_listxattr_filler (void *buf, const char *name, int namelen, | 1063 | reiserfs_listxattr_filler(void *buf, const char *name, int namelen, | 
| 1063 | loff_t offset, ino_t ino, unsigned int d_type) | 1064 | loff_t offset, ino_t ino, unsigned int d_type) | 
| 1064 | { | 1065 | { | 
| 1065 | struct reiserfs_listxattr_buf *b = (struct reiserfs_listxattr_buf *)buf; | 1066 | struct reiserfs_listxattr_buf *b = (struct reiserfs_listxattr_buf *)buf; | 
| 1066 | int len = 0; | 1067 | int len = 0; | 
| 1067 | if (name[0] != '.' || (namelen != 1 && (name[1] != '.' || namelen != 2))) { | 1068 | if (name[0] != '.' | 
| 1068 | struct reiserfs_xattr_handler *xah = find_xattr_handler_prefix (name); | 1069 | || (namelen != 1 && (name[1] != '.' || namelen != 2))) { | 
| 1069 | if (!xah) return 0; /* Unsupported xattr name, skip it */ | 1070 | struct reiserfs_xattr_handler *xah = | 
| 1070 | 1071 | find_xattr_handler_prefix(name); | |
| 1071 | /* We call ->list() twice because the operation isn't required to just | 1072 | if (!xah) | 
| 1072 | * return the name back - we want to make sure we have enough space */ | 1073 | return 0; /* Unsupported xattr name, skip it */ | 
| 1073 | len += xah->list (b->r_inode, name, namelen, NULL); | 1074 | |
| 1074 | 1075 | /* We call ->list() twice because the operation isn't required to just | |
| 1075 | if (len) { | 1076 | * return the name back - we want to make sure we have enough space */ | 
| 1076 | if (b->r_pos + len + 1 <= b->r_size) { | 1077 | len += xah->list(b->r_inode, name, namelen, NULL); | 
| 1077 | char *p = b->r_buf + b->r_pos; | 1078 | |
| 1078 | p += xah->list (b->r_inode, name, namelen, p); | 1079 | if (len) { | 
| 1079 | *p++ = '\0'; | 1080 | if (b->r_pos + len + 1 <= b->r_size) { | 
| 1080 | } | 1081 | char *p = b->r_buf + b->r_pos; | 
| 1081 | b->r_pos += len + 1; | 1082 | p += xah->list(b->r_inode, name, namelen, p); | 
| 1082 | } | 1083 | *p++ = '\0'; | 
| 1083 | } | 1084 | } | 
| 1084 | 1085 | b->r_pos += len + 1; | |
| 1085 | return 0; | 1086 | } | 
| 1087 | } | ||
| 1088 | |||
| 1089 | return 0; | ||
| 1086 | } | 1090 | } | 
| 1091 | |||
| 1087 | /* | 1092 | /* | 
| 1088 | * Inode operation listxattr() | 1093 | * Inode operation listxattr() | 
| 1089 | * | 1094 | * | 
| 1090 | * Preliminary locking: we down dentry->d_inode->i_sem | 1095 | * Preliminary locking: we down dentry->d_inode->i_sem | 
| 1091 | */ | 1096 | */ | 
| 1092 | ssize_t | 1097 | ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) | 
| 1093 | reiserfs_listxattr (struct dentry *dentry, char *buffer, size_t size) | ||
| 1094 | { | 1098 | { | 
| 1095 | struct file *fp; | 1099 | struct file *fp; | 
| 1096 | struct dentry *dir; | 1100 | struct dentry *dir; | 
| 1097 | int err = 0; | 1101 | int err = 0; | 
| 1098 | struct reiserfs_listxattr_buf buf; | 1102 | struct reiserfs_listxattr_buf buf; | 
| 1099 | 1103 | ||
| 1100 | if (!dentry->d_inode) | 1104 | if (!dentry->d_inode) | 
| 1101 | return -EINVAL; | 1105 | return -EINVAL; | 
| 1102 | 1106 | ||
| 1103 | if (!reiserfs_xattrs(dentry->d_sb) || | 1107 | if (!reiserfs_xattrs(dentry->d_sb) || | 
| 1104 | get_inode_sd_version (dentry->d_inode) == STAT_DATA_V1) | 1108 | get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) | 
| 1105 | return -EOPNOTSUPP; | 1109 | return -EOPNOTSUPP; | 
| 1106 | 1110 | ||
| 1107 | reiserfs_read_lock_xattr_i (dentry->d_inode); | 1111 | reiserfs_read_lock_xattr_i(dentry->d_inode); | 
| 1108 | reiserfs_read_lock_xattrs (dentry->d_sb); | 1112 | reiserfs_read_lock_xattrs(dentry->d_sb); | 
| 1109 | dir = open_xa_dir (dentry->d_inode, FL_READONLY); | 1113 | dir = open_xa_dir(dentry->d_inode, FL_READONLY); | 
| 1110 | reiserfs_read_unlock_xattrs (dentry->d_sb); | 1114 | reiserfs_read_unlock_xattrs(dentry->d_sb); | 
| 1111 | if (IS_ERR (dir)) { | 1115 | if (IS_ERR(dir)) { | 
| 1112 | err = PTR_ERR (dir); | 1116 | err = PTR_ERR(dir); | 
| 1113 | if (err == -ENODATA) | 1117 | if (err == -ENODATA) | 
| 1114 | err = 0; /* Not an error if there aren't any xattrs */ | 1118 | err = 0; /* Not an error if there aren't any xattrs */ | 
| 1115 | goto out; | 1119 | goto out; | 
| 1116 | } | 1120 | } | 
| 1117 | 1121 | ||
| 1118 | fp = dentry_open (dir, NULL, O_RDWR); | 1122 | fp = dentry_open(dir, NULL, O_RDWR); | 
| 1119 | if (IS_ERR (fp)) { | 1123 | if (IS_ERR(fp)) { | 
| 1120 | err = PTR_ERR (fp); | 1124 | err = PTR_ERR(fp); | 
| 1121 | /* dentry_open dputs the dentry if it fails */ | 1125 | /* dentry_open dputs the dentry if it fails */ | 
| 1122 | goto out; | 1126 | goto out; | 
| 1123 | } | 1127 | } | 
| 1124 | 1128 | ||
| 1125 | buf.r_buf = buffer; | 1129 | buf.r_buf = buffer; | 
| 1126 | buf.r_size = buffer ? size : 0; | 1130 | buf.r_size = buffer ? size : 0; | 
| 1127 | buf.r_pos = 0; | 1131 | buf.r_pos = 0; | 
| 1128 | buf.r_inode = dentry->d_inode; | 1132 | buf.r_inode = dentry->d_inode; | 
| 1129 | 1133 | ||
| 1130 | REISERFS_I(dentry->d_inode)->i_flags |= i_has_xattr_dir; | 1134 | REISERFS_I(dentry->d_inode)->i_flags |= i_has_xattr_dir; | 
| 1131 | 1135 | ||
| 1132 | err = xattr_readdir (fp, reiserfs_listxattr_filler, &buf); | 1136 | err = xattr_readdir(fp, reiserfs_listxattr_filler, &buf); | 
| 1133 | if (err) | 1137 | if (err) | 
| 1134 | goto out_dir; | 1138 | goto out_dir; | 
| 1135 | 1139 | ||
| 1136 | if (buf.r_pos > buf.r_size && buffer != NULL) | 1140 | if (buf.r_pos > buf.r_size && buffer != NULL) | 
| 1137 | err = -ERANGE; | 1141 | err = -ERANGE; | 
| 1138 | else | 1142 | else | 
| 1139 | err = buf.r_pos; | 1143 | err = buf.r_pos; | 
| 1140 | 1144 | ||
| 1141 | out_dir: | 1145 | out_dir: | 
| 1142 | fput(fp); | 1146 | fput(fp); | 
| 1143 | 1147 | ||
| 1144 | out: | 1148 | out: | 
| 1145 | reiserfs_read_unlock_xattr_i (dentry->d_inode); | 1149 | reiserfs_read_unlock_xattr_i(dentry->d_inode); | 
| 1146 | return err; | 1150 | return err; | 
| 1147 | } | 1151 | } | 
| 1148 | 1152 | ||
| 1149 | /* This is the implementation for the xattr plugin infrastructure */ | 1153 | /* This is the implementation for the xattr plugin infrastructure */ | 
| 1150 | static struct list_head xattr_handlers = LIST_HEAD_INIT (xattr_handlers); | 1154 | static struct list_head xattr_handlers = LIST_HEAD_INIT(xattr_handlers); | 
| 1151 | static DEFINE_RWLOCK(handler_lock); | 1155 | static DEFINE_RWLOCK(handler_lock); | 
| 1152 | 1156 | ||
| 1153 | static struct reiserfs_xattr_handler * | 1157 | static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char | 
| 1154 | find_xattr_handler_prefix (const char *prefix) | 1158 | *prefix) | 
| 1155 | { | 1159 | { | 
| 1156 | struct reiserfs_xattr_handler *xah = NULL; | 1160 | struct reiserfs_xattr_handler *xah = NULL; | 
| 1157 | struct list_head *p; | 1161 | struct list_head *p; | 
| 1158 | 1162 | ||
| 1159 | read_lock (&handler_lock); | 1163 | read_lock(&handler_lock); | 
| 1160 | list_for_each (p, &xattr_handlers) { | 1164 | list_for_each(p, &xattr_handlers) { | 
| 1161 | xah = list_entry (p, struct reiserfs_xattr_handler, handlers); | 1165 | xah = list_entry(p, struct reiserfs_xattr_handler, handlers); | 
| 1162 | if (strncmp (xah->prefix, prefix, strlen (xah->prefix)) == 0) | 1166 | if (strncmp(xah->prefix, prefix, strlen(xah->prefix)) == 0) | 
| 1163 | break; | 1167 | break; | 
| 1164 | xah = NULL; | 1168 | xah = NULL; | 
| 1165 | } | 1169 | } | 
| 1166 | 1170 | ||
| 1167 | read_unlock (&handler_lock); | 1171 | read_unlock(&handler_lock); | 
| 1168 | return xah; | 1172 | return xah; | 
| 1169 | } | 1173 | } | 
| 1170 | 1174 | ||
| 1171 | static void | 1175 | static void __unregister_handlers(void) | 
| 1172 | __unregister_handlers (void) | ||
| 1173 | { | 1176 | { | 
| 1174 | struct reiserfs_xattr_handler *xah; | 1177 | struct reiserfs_xattr_handler *xah; | 
| 1175 | struct list_head *p, *tmp; | 1178 | struct list_head *p, *tmp; | 
| 1176 | 1179 | ||
| 1177 | list_for_each_safe (p, tmp, &xattr_handlers) { | 1180 | list_for_each_safe(p, tmp, &xattr_handlers) { | 
| 1178 | xah = list_entry (p, struct reiserfs_xattr_handler, handlers); | 1181 | xah = list_entry(p, struct reiserfs_xattr_handler, handlers); | 
| 1179 | if (xah->exit) | 1182 | if (xah->exit) | 
| 1180 | xah->exit(); | 1183 | xah->exit(); | 
| 1181 | 1184 | ||
| 1182 | list_del_init (p); | 1185 | list_del_init(p); | 
| 1183 | } | 1186 | } | 
| 1184 | INIT_LIST_HEAD (&xattr_handlers); | 1187 | INIT_LIST_HEAD(&xattr_handlers); | 
| 1185 | } | 1188 | } | 
| 1186 | 1189 | ||
| 1187 | int __init | 1190 | int __init reiserfs_xattr_register_handlers(void) | 
| 1188 | reiserfs_xattr_register_handlers (void) | ||
| 1189 | { | 1191 | { | 
| 1190 | int err = 0; | 1192 | int err = 0; | 
| 1191 | struct reiserfs_xattr_handler *xah; | 1193 | struct reiserfs_xattr_handler *xah; | 
| 1192 | struct list_head *p; | 1194 | struct list_head *p; | 
| 1193 | 1195 | ||
| 1194 | write_lock (&handler_lock); | 1196 | write_lock(&handler_lock); | 
| 1195 | 1197 | ||
| 1196 | /* If we're already initialized, nothing to do */ | 1198 | /* If we're already initialized, nothing to do */ | 
| 1197 | if (!list_empty (&xattr_handlers)) { | 1199 | if (!list_empty(&xattr_handlers)) { | 
| 1198 | write_unlock (&handler_lock); | 1200 | write_unlock(&handler_lock); | 
| 1199 | return 0; | 1201 | return 0; | 
| 1200 | } | 1202 | } | 
| 1201 | 1203 | ||
| 1202 | /* Add the handlers */ | 1204 | /* Add the handlers */ | 
| 1203 | list_add_tail (&user_handler.handlers, &xattr_handlers); | 1205 | list_add_tail(&user_handler.handlers, &xattr_handlers); | 
| 1204 | list_add_tail (&trusted_handler.handlers, &xattr_handlers); | 1206 | list_add_tail(&trusted_handler.handlers, &xattr_handlers); | 
| 1205 | #ifdef CONFIG_REISERFS_FS_SECURITY | 1207 | #ifdef CONFIG_REISERFS_FS_SECURITY | 
| 1206 | list_add_tail (&security_handler.handlers, &xattr_handlers); | 1208 | list_add_tail(&security_handler.handlers, &xattr_handlers); | 
| 1207 | #endif | 1209 | #endif | 
| 1208 | #ifdef CONFIG_REISERFS_FS_POSIX_ACL | 1210 | #ifdef CONFIG_REISERFS_FS_POSIX_ACL | 
| 1209 | list_add_tail (&posix_acl_access_handler.handlers, &xattr_handlers); | 1211 | list_add_tail(&posix_acl_access_handler.handlers, &xattr_handlers); | 
| 1210 | list_add_tail (&posix_acl_default_handler.handlers, &xattr_handlers); | 1212 | list_add_tail(&posix_acl_default_handler.handlers, &xattr_handlers); | 
| 1211 | #endif | 1213 | #endif | 
| 1212 | 1214 | ||
| 1213 | /* Run initializers, if available */ | 1215 | /* Run initializers, if available */ | 
| 1214 | list_for_each (p, &xattr_handlers) { | 1216 | list_for_each(p, &xattr_handlers) { | 
| 1215 | xah = list_entry (p, struct reiserfs_xattr_handler, handlers); | 1217 | xah = list_entry(p, struct reiserfs_xattr_handler, handlers); | 
| 1216 | if (xah->init) { | 1218 | if (xah->init) { | 
| 1217 | err = xah->init (); | 1219 | err = xah->init(); | 
| 1218 | if (err) { | 1220 | if (err) { | 
| 1219 | list_del_init (p); | 1221 | list_del_init(p); | 
| 1220 | break; | 1222 | break; | 
| 1221 | } | 1223 | } | 
| 1222 | } | 1224 | } | 
| 1223 | } | 1225 | } | 
| 1224 | 1226 | ||
| 1225 | /* Clean up other handlers, if any failed */ | 1227 | /* Clean up other handlers, if any failed */ | 
| 1226 | if (err) | 1228 | if (err) | 
| 1227 | __unregister_handlers (); | 1229 | __unregister_handlers(); | 
| 1228 | 1230 | ||
| 1229 | write_unlock (&handler_lock); | 1231 | write_unlock(&handler_lock); | 
| 1230 | return err; | 1232 | return err; | 
| 1231 | } | 1233 | } | 
| 1232 | 1234 | ||
| 1233 | void | 1235 | void reiserfs_xattr_unregister_handlers(void) | 
| 1234 | reiserfs_xattr_unregister_handlers (void) | ||
| 1235 | { | 1236 | { | 
| 1236 | write_lock (&handler_lock); | 1237 | write_lock(&handler_lock); | 
| 1237 | __unregister_handlers (); | 1238 | __unregister_handlers(); | 
| 1238 | write_unlock (&handler_lock); | 1239 | write_unlock(&handler_lock); | 
| 1239 | } | 1240 | } | 
| 1240 | 1241 | ||
| 1241 | /* This will catch lookups from the fs root to .reiserfs_priv */ | 1242 | /* This will catch lookups from the fs root to .reiserfs_priv */ | 
| 1242 | static int | 1243 | static int | 
| 1243 | xattr_lookup_poison (struct dentry *dentry, struct qstr *q1, struct qstr *name) | 1244 | xattr_lookup_poison(struct dentry *dentry, struct qstr *q1, struct qstr *name) | 
| 1244 | { | 1245 | { | 
| 1245 | struct dentry *priv_root = REISERFS_SB(dentry->d_sb)->priv_root; | 1246 | struct dentry *priv_root = REISERFS_SB(dentry->d_sb)->priv_root; | 
| 1246 | if (name->len == priv_root->d_name.len && | 1247 | if (name->len == priv_root->d_name.len && | 
| 1247 | name->hash == priv_root->d_name.hash && | 1248 | name->hash == priv_root->d_name.hash && | 
| 1248 | !memcmp (name->name, priv_root->d_name.name, name->len)) { | 1249 | !memcmp(name->name, priv_root->d_name.name, name->len)) { | 
| 1249 | return -ENOENT; | 1250 | return -ENOENT; | 
| 1250 | } else if (q1->len == name->len && | 1251 | } else if (q1->len == name->len && | 
| 1251 | !memcmp(q1->name, name->name, name->len)) | 1252 | !memcmp(q1->name, name->name, name->len)) | 
| 1252 | return 0; | 1253 | return 0; | 
| 1253 | return 1; | 1254 | return 1; | 
| 1254 | } | 1255 | } | 
| 1255 | 1256 | ||
| 1256 | static struct dentry_operations xattr_lookup_poison_ops = { | 1257 | static struct dentry_operations xattr_lookup_poison_ops = { | 
| 1257 | .d_compare = xattr_lookup_poison, | 1258 | .d_compare = xattr_lookup_poison, | 
| 1258 | }; | 1259 | }; | 
| 1259 | 1260 | ||
| 1260 | |||
| 1261 | /* We need to take a copy of the mount flags since things like | 1261 | /* We need to take a copy of the mount flags since things like | 
| 1262 | * MS_RDONLY don't get set until *after* we're called. | 1262 | * MS_RDONLY don't get set until *after* we're called. | 
| 1263 | * mount_flags != mount_options */ | 1263 | * mount_flags != mount_options */ | 
| 1264 | int | 1264 | int reiserfs_xattr_init(struct super_block *s, int mount_flags) | 
| 1265 | reiserfs_xattr_init (struct super_block *s, int mount_flags) | ||
| 1266 | { | 1265 | { | 
| 1267 | int err = 0; | 1266 | int err = 0; | 
| 1268 | 1267 | ||
| 1269 | /* We need generation numbers to ensure that the oid mapping is correct | 1268 | /* We need generation numbers to ensure that the oid mapping is correct | 
| 1270 | * v3.5 filesystems don't have them. */ | 1269 | * v3.5 filesystems don't have them. */ | 
| 1271 | if (!old_format_only (s)) { | 1270 | if (!old_format_only(s)) { | 
| 1272 | set_bit (REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt)); | 1271 | set_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt)); | 
| 1273 | } else if (reiserfs_xattrs_optional (s)) { | 1272 | } else if (reiserfs_xattrs_optional(s)) { | 
| 1274 | /* Old format filesystem, but optional xattrs have been enabled | 1273 | /* Old format filesystem, but optional xattrs have been enabled | 
| 1275 | * at mount time. Error out. */ | 1274 | * at mount time. Error out. */ | 
| 1276 | reiserfs_warning (s, "xattrs/ACLs not supported on pre v3.6 " | 1275 | reiserfs_warning(s, "xattrs/ACLs not supported on pre v3.6 " | 
| 1277 | "format filesystem. Failing mount."); | 1276 | "format filesystem. Failing mount."); | 
| 1278 | err = -EOPNOTSUPP; | 1277 | err = -EOPNOTSUPP; | 
| 1279 | goto error; | 1278 | goto error; | 
| 1280 | } else { | 1279 | } else { | 
| 1281 | /* Old format filesystem, but no optional xattrs have been enabled. This | 1280 | /* Old format filesystem, but no optional xattrs have been enabled. This | 
| 1282 | * means we silently disable xattrs on the filesystem. */ | 1281 | * means we silently disable xattrs on the filesystem. */ | 
| 1283 | clear_bit (REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt)); | 1282 | clear_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt)); | 
| 1284 | } | 1283 | } | 
| 1285 | 1284 | ||
| 1286 | /* If we don't have the privroot located yet - go find it */ | 1285 | /* If we don't have the privroot located yet - go find it */ | 
| 1287 | if (reiserfs_xattrs (s) && !REISERFS_SB(s)->priv_root) { | 1286 | if (reiserfs_xattrs(s) && !REISERFS_SB(s)->priv_root) { | 
| 1288 | struct dentry *dentry; | 1287 | struct dentry *dentry; | 
| 1289 | dentry = lookup_one_len (PRIVROOT_NAME, s->s_root, | 1288 | dentry = lookup_one_len(PRIVROOT_NAME, s->s_root, | 
| 1290 | strlen (PRIVROOT_NAME)); | 1289 | strlen(PRIVROOT_NAME)); | 
| 1291 | if (!IS_ERR (dentry)) { | 1290 | if (!IS_ERR(dentry)) { | 
| 1292 | if (!(mount_flags & MS_RDONLY) && !dentry->d_inode) { | 1291 | if (!(mount_flags & MS_RDONLY) && !dentry->d_inode) { | 
| 1293 | struct inode *inode = dentry->d_parent->d_inode; | 1292 | struct inode *inode = dentry->d_parent->d_inode; | 
| 1294 | down (&inode->i_sem); | 1293 | down(&inode->i_sem); | 
| 1295 | err = inode->i_op->mkdir (inode, dentry, 0700); | 1294 | err = inode->i_op->mkdir(inode, dentry, 0700); | 
| 1296 | up (&inode->i_sem); | 1295 | up(&inode->i_sem); | 
| 1297 | if (err) { | 1296 | if (err) { | 
| 1298 | dput (dentry); | 1297 | dput(dentry); | 
| 1299 | dentry = NULL; | 1298 | dentry = NULL; | 
| 1300 | } | 1299 | } | 
| 1301 | 1300 | ||
| 1302 | if (dentry && dentry->d_inode) | 1301 | if (dentry && dentry->d_inode) | 
| 1303 | reiserfs_warning (s, "Created %s on %s - reserved for " | 1302 | reiserfs_warning(s, | 
| 1304 | "xattr storage.", PRIVROOT_NAME, | 1303 | "Created %s on %s - reserved for " | 
| 1305 | reiserfs_bdevname (inode->i_sb)); | 1304 | "xattr storage.", | 
| 1306 | } else if (!dentry->d_inode) { | 1305 | PRIVROOT_NAME, | 
| 1307 | dput (dentry); | 1306 | reiserfs_bdevname | 
| 1308 | dentry = NULL; | 1307 | (inode->i_sb)); | 
| 1309 | } | 1308 | } else if (!dentry->d_inode) { | 
| 1310 | } else | 1309 | dput(dentry); | 
| 1311 | err = PTR_ERR (dentry); | 1310 | dentry = NULL; | 
| 1312 | 1311 | } | |
| 1313 | if (!err && dentry) { | 1312 | } else | 
| 1314 | s->s_root->d_op = &xattr_lookup_poison_ops; | 1313 | err = PTR_ERR(dentry); | 
| 1315 | reiserfs_mark_inode_private (dentry->d_inode); | 1314 | |
| 1316 | REISERFS_SB(s)->priv_root = dentry; | 1315 | if (!err && dentry) { | 
| 1317 | } else if (!(mount_flags & MS_RDONLY)) { /* xattrs are unavailable */ | 1316 | s->s_root->d_op = &xattr_lookup_poison_ops; | 
| 1318 | /* If we're read-only it just means that the dir hasn't been | 1317 | reiserfs_mark_inode_private(dentry->d_inode); | 
| 1319 | * created. Not an error -- just no xattrs on the fs. We'll | 1318 | REISERFS_SB(s)->priv_root = dentry; | 
| 1320 | * check again if we go read-write */ | 1319 | } else if (!(mount_flags & MS_RDONLY)) { /* xattrs are unavailable */ | 
| 1321 | reiserfs_warning (s, "xattrs/ACLs enabled and couldn't " | 1320 | /* If we're read-only it just means that the dir hasn't been | 
| 1322 | "find/create .reiserfs_priv. Failing mount."); | 1321 | * created. Not an error -- just no xattrs on the fs. We'll | 
| 1323 | err = -EOPNOTSUPP; | 1322 | * check again if we go read-write */ | 
| 1324 | } | 1323 | reiserfs_warning(s, "xattrs/ACLs enabled and couldn't " | 
| 1325 | } | 1324 | "find/create .reiserfs_priv. Failing mount."); | 
| 1326 | 1325 | err = -EOPNOTSUPP; | |
| 1327 | error: | 1326 | } | 
| 1328 | /* This is only nonzero if there was an error initializing the xattr | 1327 | } | 
| 1329 | * directory or if there is a condition where we don't support them. */ | 1328 | |
| 1330 | if (err) { | 1329 | error: | 
| 1331 | clear_bit (REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt)); | 1330 | /* This is only nonzero if there was an error initializing the xattr | 
| 1332 | clear_bit (REISERFS_XATTRS_USER, &(REISERFS_SB(s)->s_mount_opt)); | 1331 | * directory or if there is a condition where we don't support them. */ | 
| 1333 | clear_bit (REISERFS_POSIXACL, &(REISERFS_SB(s)->s_mount_opt)); | 1332 | if (err) { | 
| 1334 | } | 1333 | clear_bit(REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt)); | 
| 1335 | 1334 | clear_bit(REISERFS_XATTRS_USER, &(REISERFS_SB(s)->s_mount_opt)); | |
| 1336 | /* The super_block MS_POSIXACL must mirror the (no)acl mount option. */ | 1335 | clear_bit(REISERFS_POSIXACL, &(REISERFS_SB(s)->s_mount_opt)); | 
| 1337 | s->s_flags = s->s_flags & ~MS_POSIXACL; | 1336 | } | 
| 1338 | if (reiserfs_posixacl (s)) | 1337 | |
| 1339 | s->s_flags |= MS_POSIXACL; | 1338 | /* The super_block MS_POSIXACL must mirror the (no)acl mount option. */ | 
| 1340 | 1339 | s->s_flags = s->s_flags & ~MS_POSIXACL; | |
| 1341 | return err; | 1340 | if (reiserfs_posixacl(s)) | 
| 1341 | s->s_flags |= MS_POSIXACL; | ||
| 1342 | |||
| 1343 | return err; | ||
| 1342 | } | 1344 | } | 
| 1343 | 1345 | ||
| 1344 | static int | 1346 | static int | 
| 1345 | __reiserfs_permission (struct inode *inode, int mask, struct nameidata *nd, | 1347 | __reiserfs_permission(struct inode *inode, int mask, struct nameidata *nd, | 
| 1346 | int need_lock) | 1348 | int need_lock) | 
| 1347 | { | 1349 | { | 
| 1348 | umode_t mode = inode->i_mode; | 1350 | umode_t mode = inode->i_mode; | 
| 1349 | 1351 | ||
| 1350 | if (mask & MAY_WRITE) { | 1352 | if (mask & MAY_WRITE) { | 
| 1351 | /* | 1353 | /* | 
| @@ -1363,50 +1365,50 @@ __reiserfs_permission (struct inode *inode, int mask, struct nameidata *nd, | |||
| 1363 | } | 1365 | } | 
| 1364 | 1366 | ||
| 1365 | /* We don't do permission checks on the internal objects. | 1367 | /* We don't do permission checks on the internal objects. | 
| 1366 | * Permissions are determined by the "owning" object. */ | 1368 | * Permissions are determined by the "owning" object. */ | 
| 1367 | if (is_reiserfs_priv_object (inode)) | 1369 | if (is_reiserfs_priv_object(inode)) | 
| 1368 | return 0; | 1370 | return 0; | 
| 1369 | 1371 | ||
| 1370 | if (current->fsuid == inode->i_uid) { | 1372 | if (current->fsuid == inode->i_uid) { | 
| 1371 | mode >>= 6; | 1373 | mode >>= 6; | 
| 1372 | #ifdef CONFIG_REISERFS_FS_POSIX_ACL | 1374 | #ifdef CONFIG_REISERFS_FS_POSIX_ACL | 
| 1373 | } else if (reiserfs_posixacl(inode->i_sb) && | 1375 | } else if (reiserfs_posixacl(inode->i_sb) && | 
| 1374 | get_inode_sd_version (inode) != STAT_DATA_V1) { | 1376 | get_inode_sd_version(inode) != STAT_DATA_V1) { | 
| 1375 | struct posix_acl *acl; | 1377 | struct posix_acl *acl; | 
| 1376 | 1378 | ||
| 1377 | /* ACL can't contain additional permissions if | 1379 | /* ACL can't contain additional permissions if | 
| 1378 | the ACL_MASK entry is 0 */ | 1380 | the ACL_MASK entry is 0 */ | 
| 1379 | if (!(mode & S_IRWXG)) | 1381 | if (!(mode & S_IRWXG)) | 
| 1380 | goto check_groups; | 1382 | goto check_groups; | 
| 1381 | 1383 | ||
| 1382 | if (need_lock) { | 1384 | if (need_lock) { | 
| 1383 | reiserfs_read_lock_xattr_i (inode); | 1385 | reiserfs_read_lock_xattr_i(inode); | 
| 1384 | reiserfs_read_lock_xattrs (inode->i_sb); | 1386 | reiserfs_read_lock_xattrs(inode->i_sb); | 
| 1387 | } | ||
| 1388 | acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); | ||
| 1389 | if (need_lock) { | ||
| 1390 | reiserfs_read_unlock_xattrs(inode->i_sb); | ||
| 1391 | reiserfs_read_unlock_xattr_i(inode); | ||
| 1385 | } | 1392 | } | 
| 1386 | acl = reiserfs_get_acl (inode, ACL_TYPE_ACCESS); | 1393 | if (IS_ERR(acl)) { | 
| 1387 | if (need_lock) { | 1394 | if (PTR_ERR(acl) == -ENODATA) | 
| 1388 | reiserfs_read_unlock_xattrs (inode->i_sb); | 1395 | goto check_groups; | 
| 1389 | reiserfs_read_unlock_xattr_i (inode); | 1396 | return PTR_ERR(acl); | 
| 1390 | } | 1397 | } | 
| 1391 | if (IS_ERR (acl)) { | 1398 | |
| 1392 | if (PTR_ERR (acl) == -ENODATA) | 1399 | if (acl) { | 
| 1393 | goto check_groups; | 1400 | int err = posix_acl_permission(inode, acl, mask); | 
| 1394 | return PTR_ERR (acl); | 1401 | posix_acl_release(acl); | 
| 1395 | } | 1402 | if (err == -EACCES) { | 
| 1396 | 1403 | goto check_capabilities; | |
| 1397 | if (acl) { | 1404 | } | 
| 1398 | int err = posix_acl_permission (inode, acl, mask); | 1405 | return err; | 
| 1399 | posix_acl_release (acl); | ||
| 1400 | if (err == -EACCES) { | ||
| 1401 | goto check_capabilities; | ||
| 1402 | } | ||
| 1403 | return err; | ||
| 1404 | } else { | 1406 | } else { | 
| 1405 | goto check_groups; | 1407 | goto check_groups; | 
| 1406 | } | 1408 | } | 
| 1407 | #endif | 1409 | #endif | 
| 1408 | } else { | 1410 | } else { | 
| 1409 | check_groups: | 1411 | check_groups: | 
| 1410 | if (in_group_p(inode->i_gid)) | 1412 | if (in_group_p(inode->i_gid)) | 
| 1411 | mode >>= 3; | 1413 | mode >>= 3; | 
| 1412 | } | 1414 | } | 
| @@ -1414,10 +1416,10 @@ check_groups: | |||
| 1414 | /* | 1416 | /* | 
| 1415 | * If the DACs are ok we don't need any capability check. | 1417 | * If the DACs are ok we don't need any capability check. | 
| 1416 | */ | 1418 | */ | 
| 1417 | if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask)) | 1419 | if (((mode & mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == mask)) | 
| 1418 | return 0; | 1420 | return 0; | 
| 1419 | 1421 | ||
| 1420 | check_capabilities: | 1422 | check_capabilities: | 
| 1421 | /* | 1423 | /* | 
| 1422 | * Read/write DACs are always overridable. | 1424 | * Read/write DACs are always overridable. | 
| 1423 | * Executable DACs are overridable if at least one exec bit is set. | 1425 | * Executable DACs are overridable if at least one exec bit is set. | 
| @@ -1437,14 +1439,13 @@ check_capabilities: | |||
| 1437 | return -EACCES; | 1439 | return -EACCES; | 
| 1438 | } | 1440 | } | 
| 1439 | 1441 | ||
| 1440 | int | 1442 | int reiserfs_permission(struct inode *inode, int mask, struct nameidata *nd) | 
| 1441 | reiserfs_permission (struct inode *inode, int mask, struct nameidata *nd) | ||
| 1442 | { | 1443 | { | 
| 1443 | return __reiserfs_permission (inode, mask, nd, 1); | 1444 | return __reiserfs_permission(inode, mask, nd, 1); | 
| 1444 | } | 1445 | } | 
| 1445 | 1446 | ||
| 1446 | int | 1447 | int | 
| 1447 | reiserfs_permission_locked (struct inode *inode, int mask, struct nameidata *nd) | 1448 | reiserfs_permission_locked(struct inode *inode, int mask, struct nameidata *nd) | 
| 1448 | { | 1449 | { | 
| 1449 | return __reiserfs_permission (inode, mask, nd, 0); | 1450 | return __reiserfs_permission(inode, mask, nd, 0); | 
| 1450 | } | 1451 | } | 
